[automerger skipped] Specify KeyMint EC keys by curve not size am: bd3d12a377 am: 09afca29d3 -s ours

am skip reason: Merged-In Ia6b7d86a387cfc06db05e4ba6ff8f331e9c6345f with SHA-1 915ce253a8 is already in history

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

Change-Id: I77aca69512167b855d0e037ca7d25d1052d26faa
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/Android.bp b/Android.bp
index 815e766..fc6babe 100644
--- a/Android.bp
+++ b/Android.bp
@@ -58,8 +58,6 @@
         "libhidl_gtest_helper",
     ],
 
-    group_static_libs: true,
-
     // Lists all system dependencies that can be expected on the device.
     shared_libs: [
         "libbase",
diff --git a/atrace/1.0/vts/functional/OWNERS b/atrace/1.0/vts/functional/OWNERS
new file mode 100644
index 0000000..31043aa
--- /dev/null
+++ b/atrace/1.0/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 837454
+wvw@google.com
diff --git a/audio/7.0/config/update_audio_policy_config.sh b/audio/7.0/config/update_audio_policy_config.sh
index 159fa35..c475dd1 100755
--- a/audio/7.0/config/update_audio_policy_config.sh
+++ b/audio/7.0/config/update_audio_policy_config.sh
@@ -41,7 +41,7 @@
 
 set -euo pipefail
 
-if (echo "$@" | grep -qe -h); then
+if (echo "$@" | grep -qe "^-h"); then
     echo "This script will update Audio Policy Manager config file"
     echo "to the format required by V7.0 XSD schema from a previous"
     echo "version."
diff --git a/audio/7.1/Android.bp b/audio/7.1/Android.bp
new file mode 100644
index 0000000..cede72a
--- /dev/null
+++ b/audio/7.1/Android.bp
@@ -0,0 +1,31 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+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"],
+}
+
+hidl_interface {
+    name: "android.hardware.audio@7.1",
+    root: "android.hardware",
+    srcs: [
+        "types.hal",
+        "IDevice.hal",
+        "IDevicesFactory.hal",
+        "IPrimaryDevice.hal",
+        "IStreamOut.hal",
+        "IStreamOutLatencyModeCallback.hal",
+    ],
+    interfaces: [
+        "android.hardware.audio@7.0",
+        "android.hardware.audio.common@7.0",
+        "android.hidl.base@1.0",
+        "android.hidl.safe_union@1.0",
+    ],
+    gen_java: false,
+    gen_java_constants: false,
+}
diff --git a/audio/7.1/IDevice.hal b/audio/7.1/IDevice.hal
new file mode 100644
index 0000000..c158e7e
--- /dev/null
+++ b/audio/7.1/IDevice.hal
@@ -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.audio@7.1;
+
+import android.hardware.audio.common@7.0;
+import @7.0::AudioInOutFlag;
+import @7.0::IDevice;
+import @7.0::Result;
+import IStreamOut;
+
+interface IDevice extends @7.0::IDevice {
+    /**
+     * This method creates and opens the audio hardware output stream.
+     * If the stream can not be opened with the proposed audio config,
+     * HAL must provide suggested values for the audio config.
+     *
+     * Note: INVALID_ARGUMENTS is returned both in the case when the
+     * HAL can not use the provided config and in the case when
+     * the value of any argument is invalid. In the latter case the
+     * HAL must provide a default initialized suggested config.
+     *
+     * @param ioHandle handle assigned by AudioFlinger.
+     * @param device device type and (if needed) address.
+     * @param config stream configuration.
+     * @param flags additional flags.
+     * @param sourceMetadata Description of the audio that will be played.
+                             May be used by implementations to configure hardware effects.
+     * @return retval operation completion status.
+     * @return outStream created output stream.
+     * @return suggestedConfig in the case of rejection of the proposed config,
+     *                         a config suggested by the HAL.
+     */
+    openOutputStream_7_1(
+            AudioIoHandle ioHandle,
+            DeviceAddress device,
+            AudioConfig config,
+            vec<AudioInOutFlag> flags,
+            SourceMetadata sourceMetadata) generates (
+                    Result retval,
+                    IStreamOut outStream,
+                    AudioConfig suggestedConfig);
+
+    /**
+     * Notifies the device module about the connection state of an input/output
+     * device attached to it. The devicePort identifies the device and may also
+     * provide extra information such as raw audio descriptors.
+     *
+     * @param devicePort audio device port.
+     * @param connected whether the device is connected.
+     * @return retval operation completion status.
+     */
+    setConnectedState_7_1(AudioPort devicePort, bool connected)
+            generates (Result retval);
+};
diff --git a/audio/7.1/IDevicesFactory.hal b/audio/7.1/IDevicesFactory.hal
new file mode 100644
index 0000000..7669614
--- /dev/null
+++ b/audio/7.1/IDevicesFactory.hal
@@ -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.
+ */
+
+package android.hardware.audio@7.1;
+
+import @7.0::IDevicesFactory;
+import @7.0::Result;
+import IDevice;
+import IPrimaryDevice;
+
+/**
+ * This factory allows a HAL implementation to be split in multiple independent
+ * devices (called module in the pre-treble API). Note that this division is
+ * arbitrary and implementation are free to only have a Primary. The framework
+ * will query the devices according to audio_policy_configuration.xml
+ *
+ * Each device name is arbitrary, provided by the vendor's audio_policy_configuration.xml
+ * and only used to identify a device in this factory.
+ * The framework must not interpret the name, treating it as a vendor opaque data
+ * with the following exception:
+ * - the "r_submix" device that must be present to support policyMixes (Eg: Android projected).
+ *   Note that this Device is included by default in a build derived from AOSP.
+ */
+interface IDevicesFactory extends @7.0::IDevicesFactory {
+
+    /**
+     * Opens an audio device. To close the device, it is necessary to call
+     * 'close' method on the returned device object.
+     *
+     * Important note: due to rules of HIDL, @7.1::IPrimaryDevice extends
+     * @7.0::IPrimaryDevice, rather than @7.1::IDevice. Thus the returned
+     * IDevice interface can not be up-casted to @7.1::IPrimaryDevice for the
+     * primary device. The client needs to use IPrimaryDevice instead of this
+     * method if it needs full functionality of the IPrimaryDevice interface.
+     *
+     * @param device device name.
+     * @return retval operation completion status. Returns INVALID_ARGUMENTS
+     *         if there is no corresponding hardware module found,
+     *         NOT_INITIALIZED if an error occurred while opening the hardware
+     *         module.
+     * @return result the interface for the created device.
+     */
+    openDevice_7_1(string device) generates (Result retval, IDevice result);
+
+    /**
+     * Opens the Primary audio device that must be present.
+     * This function is not optional and must return successfully the primary device.
+     *
+     * This device must have the name "primary".
+     *
+     * The telephony stack uses this device to control the audio during a voice call.
+     *
+     * @return retval operation completion status. Must be SUCCESS.
+     *         For debugging, return INVALID_ARGUMENTS if there is no corresponding
+     *         hardware module found, NOT_INITIALIZED if an error occurred
+     *         while opening the hardware module.
+     * @return result the interface for the created device.
+     */
+    openPrimaryDevice_7_1() generates (Result retval, IPrimaryDevice result);
+};
diff --git a/audio/7.1/IPrimaryDevice.hal b/audio/7.1/IPrimaryDevice.hal
new file mode 100644
index 0000000..1659671
--- /dev/null
+++ b/audio/7.1/IPrimaryDevice.hal
@@ -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.audio@7.1;
+
+import android.hardware.audio.common@7.0;
+import @7.0::IPrimaryDevice;
+import IDevice;
+
+interface IPrimaryDevice extends @7.0::IPrimaryDevice {
+    /**
+     * Retrieve the generic @7.1::IDevice interface.
+     *
+     * Since @7.1::IPrimaryDevice extends @7.0::IPrimaryDevice, the interface
+     * reference can not be downcasted to @7.1::IDevice using standard methods.
+     * For this reason a dedicated interface method is provided.
+     *
+     * @return result the generic part of the interface.
+     */
+    getDevice() generates (IDevice result);
+};
diff --git a/audio/7.1/IStreamOut.hal b/audio/7.1/IStreamOut.hal
new file mode 100644
index 0000000..b2013cf
--- /dev/null
+++ b/audio/7.1/IStreamOut.hal
@@ -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.audio@7.1;
+
+import @7.0::Result;
+import @7.0::IStreamOut;
+
+import IStreamOutLatencyModeCallback;
+
+interface IStreamOut extends @7.0::IStreamOut {
+    /**
+     * Indicates the requested latency mode for this output stream.
+     *
+     * The requested mode can be one of the modes returned by
+     * getRecommendedLatencyModes() API.
+     *
+     * Optional method.
+     * Mandated only on specific spatial audio streams indicated by
+     * AUDIO_OUTPUT_FLAG_SPATIALIZER flag if they can be routed to a BT classic sink.
+     *
+     * @return retval operation completion status.
+     */
+    setLatencyMode(LatencyMode mode) generates (Result retval);
+
+    /**
+     * Indicates which latency modes are currently supported on this output stream.
+     * If the transport protocol (e.g Bluetooth A2DP) used by this output stream to reach
+     * the output device supports variable latency modes, the HAL indicates which
+     * modes are currently supported.
+     * The framework can then call setLatencyMode() with one of the supported modes to select
+     * the desired operation mode.
+     *
+     * Optional method.
+     * Mandated only on specific spatial audio streams indicated by
+     * AUDIO_OUTPUT_FLAG_SPATIALIZER flag if they can be routed to a BT classic sink.
+     *
+     * @return retval operation completion status.
+     * @return modes currrently supported latency modes.
+     */
+    getRecommendedLatencyModes() generates (Result retval, vec<LatencyMode> modes);
+
+    /**
+     * Set the callback interface for notifying changes in supported latency modes.
+     *
+     * Calling this method with a null pointer will result in releasing
+     * the callback.
+     *
+     * Optional method.
+     * Mandated only on specific spatial audio streams indicated by
+     * AUDIO_OUTPUT_FLAG_SPATIALIZER flag if they can be routed to a BT classic sink.
+     *
+     * @return retval operation completion status.
+     */
+    setLatencyModeCallback(IStreamOutLatencyModeCallback callback) generates (Result retval);
+};
diff --git a/audio/7.1/IStreamOutLatencyModeCallback.hal b/audio/7.1/IStreamOutLatencyModeCallback.hal
new file mode 100644
index 0000000..45b453f
--- /dev/null
+++ b/audio/7.1/IStreamOutLatencyModeCallback.hal
@@ -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.audio@7.1;
+
+/**
+ * Callback interface for output stream variable latency mode feature.
+ */
+interface IStreamOutLatencyModeCallback {
+    /**
+     * Called with the new list of supported latency modes when a change occurs.
+     */
+    oneway onRecommendedLatencyModeChanged(vec<LatencyMode> modes);
+};
diff --git a/audio/7.1/config/Android.bp b/audio/7.1/config/Android.bp
new file mode 100644
index 0000000..70c8fd4
--- /dev/null
+++ b/audio/7.1/config/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"],
+}
+
+xsd_config {
+    name: "audio_policy_configuration_V7_1",
+    srcs: ["audio_policy_configuration.xsd"],
+    package_name: "android.audio.policy.configuration.V7_1",
+    nullability: true,
+}
+
+xsd_config {
+    name: "audio_policy_configuration_V7_1_enums",
+    srcs: ["audio_policy_configuration.xsd"],
+    package_name: "android.audio.policy.configuration.V7_1",
+    nullability: true,
+    enums_only: true,
+}
+
+xsd_config {
+    name: "audio_policy_configuration_V7_1_parser",
+    srcs: ["audio_policy_configuration.xsd"],
+    package_name: "android.audio.policy.configuration.V7_1",
+    nullability: true,
+    parser_only: true,
+}
diff --git a/audio/7.1/config/api/current.txt b/audio/7.1/config/api/current.txt
new file mode 100644
index 0000000..75fc5c0
--- /dev/null
+++ b/audio/7.1/config/api/current.txt
@@ -0,0 +1,603 @@
+// Signature format: 2.0
+package android.audio.policy.configuration.V7_1 {
+
+  public class AttachedDevices {
+    ctor public AttachedDevices();
+    method @Nullable public java.util.List<java.lang.String> getItem();
+  }
+
+  public enum AudioChannelMask {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_1;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_10;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_11;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_12;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_13;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_14;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_15;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_16;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_17;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_18;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_19;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_2;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_20;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_21;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_22;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_23;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_24;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_3;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_4;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_5;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_6;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_7;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_8;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_INDEX_MASK_9;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_IN_2POINT0POINT2;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_IN_2POINT1POINT2;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_IN_3POINT0POINT2;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_IN_3POINT1POINT2;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_IN_5POINT1;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_IN_6;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_IN_FRONT_BACK;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_IN_MONO;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_IN_STEREO;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_IN_VOICE_CALL_MONO;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_NONE;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_13POINT_360RA;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_22POINT2;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_2POINT0POINT2;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_2POINT1;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_2POINT1POINT2;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_3POINT0POINT2;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_3POINT1;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_3POINT1POINT2;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_5POINT1;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_5POINT1POINT2;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_5POINT1POINT4;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_5POINT1_BACK;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_5POINT1_SIDE;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_6POINT1;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_7POINT1;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_7POINT1POINT2;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_7POINT1POINT4;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_9POINT1POINT4;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_9POINT1POINT6;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_HAPTIC_AB;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_MONO;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_MONO_HAPTIC_A;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_MONO_HAPTIC_AB;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_PENTA;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_QUAD;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_QUAD_BACK;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_QUAD_SIDE;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_STEREO;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_STEREO_HAPTIC_A;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_STEREO_HAPTIC_AB;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_SURROUND;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_TRI;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioChannelMask AUDIO_CHANNEL_OUT_TRI_BACK;
+  }
+
+  public enum AudioContentType {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioContentType AUDIO_CONTENT_TYPE_MOVIE;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioContentType AUDIO_CONTENT_TYPE_MUSIC;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioContentType AUDIO_CONTENT_TYPE_SONIFICATION;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioContentType AUDIO_CONTENT_TYPE_SPEECH;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioContentType AUDIO_CONTENT_TYPE_ULTRASOUND;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioContentType AUDIO_CONTENT_TYPE_UNKNOWN;
+  }
+
+  public enum AudioDevice {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_AMBIENT;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_AUX_DIGITAL;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_BACK_MIC;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_BLE_HEADSET;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_BLUETOOTH_A2DP;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_BLUETOOTH_BLE;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_BUILTIN_MIC;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_BUS;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_COMMUNICATION;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_DEFAULT;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_ECHO_REFERENCE;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_FM_TUNER;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_HDMI;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_HDMI_ARC;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_HDMI_EARC;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_IP;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_LINE;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_LOOPBACK;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_PROXY;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_REMOTE_SUBMIX;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_SPDIF;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_STUB;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_TELEPHONY_RX;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_TV_TUNER;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_USB_ACCESSORY;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_USB_DEVICE;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_USB_HEADSET;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_VOICE_CALL;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_IN_WIRED_HEADSET;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_NONE;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_AUX_DIGITAL;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_AUX_LINE;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_BLE_BROADCAST;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_BLE_HEADSET;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_BLE_SPEAKER;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_BLUETOOTH_SCO;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_BUS;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_DEFAULT;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_EARPIECE;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_ECHO_CANCELLER;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_FM;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_HDMI;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_HDMI_ARC;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_HDMI_EARC;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_HEARING_AID;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_IP;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_LINE;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_PROXY;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_SPDIF;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_SPEAKER;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_SPEAKER_SAFE;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_STUB;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_TELEPHONY_TX;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_USB_ACCESSORY;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_USB_DEVICE;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_USB_HEADSET;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioDevice AUDIO_DEVICE_OUT_WIRED_HEADSET;
+  }
+
+  public enum AudioEncapsulationType {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioEncapsulationType AUDIO_ENCAPSULATION_TYPE_IEC61937;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioEncapsulationType AUDIO_ENCAPSULATION_TYPE_NONE;
+  }
+
+  public enum AudioFormat {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_ADIF;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_ADTS;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_ADTS_ELD;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_ADTS_ERLC;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_ADTS_HE_V1;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_ADTS_HE_V2;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_ADTS_LC;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_ADTS_LD;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_ADTS_LTP;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_ADTS_MAIN;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_ADTS_SCALABLE;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_ADTS_SSR;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_ADTS_XHE;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_ELD;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_ERLC;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_HE_V1;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_HE_V2;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_LATM;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_LATM_HE_V1;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_LATM_HE_V2;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_LATM_LC;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_LC;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_LD;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_LTP;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_MAIN;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_SCALABLE;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_SSR;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AAC_XHE;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AC3;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AC4;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_ALAC;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AMR_NB;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AMR_WB;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_AMR_WB_PLUS;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_APE;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_APTX;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_APTX_ADAPTIVE;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_APTX_HD;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_APTX_TWSP;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_CELT;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_DEFAULT;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_DOLBY_TRUEHD;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_DRA;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_DSD;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_DTS;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_DTS_HD;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_DTS_UHD;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_EVRC;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_EVRCB;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_EVRCNW;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_EVRCWB;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_E_AC3;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_E_AC3_JOC;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_FLAC;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_HE_AAC_V1;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_HE_AAC_V2;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_IEC60958;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_IEC61937;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_LC3;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_LDAC;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_LHDC;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_LHDC_LL;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_MAT;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_MAT_1_0;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_MAT_2_0;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_MAT_2_1;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_MP2;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_MP3;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_MPEGH_BL_L3;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_MPEGH_BL_L4;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_MPEGH_LC_L3;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_MPEGH_LC_L4;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_OPUS;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_PCM_16_BIT;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_PCM_24_BIT_PACKED;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_PCM_32_BIT;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_PCM_8_24_BIT;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_PCM_8_BIT;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_PCM_FLOAT;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_QCELP;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_SBC;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_VORBIS;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_WMA;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioFormat AUDIO_FORMAT_WMA_PRO;
+  }
+
+  public enum AudioGainMode {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioGainMode AUDIO_GAIN_MODE_CHANNELS;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioGainMode AUDIO_GAIN_MODE_JOINT;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioGainMode AUDIO_GAIN_MODE_RAMP;
+  }
+
+  public enum AudioInOutFlag {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_INPUT_FLAG_DIRECT;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_INPUT_FLAG_FAST;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_INPUT_FLAG_HW_AV_SYNC;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_INPUT_FLAG_HW_HOTWORD;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_INPUT_FLAG_MMAP_NOIRQ;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_INPUT_FLAG_RAW;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_INPUT_FLAG_SYNC;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_INPUT_FLAG_ULTRASOUND;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_INPUT_FLAG_VOIP_TX;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_DIRECT;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_DIRECT_PCM;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_FAST;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_HW_AV_SYNC;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_INCALL_MUSIC;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_MMAP_NOIRQ;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_NON_BLOCKING;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_PRIMARY;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_RAW;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_SPATIALIZER;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_SYNC;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_TTS;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_ULTRASOUND;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_VOIP_RX;
+  }
+
+  public class AudioPolicyConfiguration {
+    ctor public AudioPolicyConfiguration();
+    method @Nullable public android.audio.policy.configuration.V7_1.GlobalConfiguration getGlobalConfiguration();
+    method @Nullable public java.util.List<android.audio.policy.configuration.V7_1.Modules> getModules();
+    method @Nullable public android.audio.policy.configuration.V7_1.SurroundSound getSurroundSound();
+    method @Nullable public android.audio.policy.configuration.V7_1.Version getVersion();
+    method @Nullable public java.util.List<android.audio.policy.configuration.V7_1.Volumes> getVolumes();
+    method public void setGlobalConfiguration(@Nullable android.audio.policy.configuration.V7_1.GlobalConfiguration);
+    method public void setSurroundSound(@Nullable android.audio.policy.configuration.V7_1.SurroundSound);
+    method public void setVersion(@Nullable android.audio.policy.configuration.V7_1.Version);
+  }
+
+  public enum AudioSource {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_CAMCORDER;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_DEFAULT;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_ECHO_REFERENCE;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_FM_TUNER;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_HOTWORD;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_MIC;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_REMOTE_SUBMIX;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_ULTRASOUND;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_UNPROCESSED;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_VOICE_CALL;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_VOICE_COMMUNICATION;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_VOICE_DOWNLINK;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_VOICE_PERFORMANCE;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_VOICE_RECOGNITION;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_VOICE_UPLINK;
+  }
+
+  public enum AudioStreamType {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioStreamType AUDIO_STREAM_ACCESSIBILITY;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioStreamType AUDIO_STREAM_ALARM;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioStreamType AUDIO_STREAM_ASSISTANT;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioStreamType AUDIO_STREAM_BLUETOOTH_SCO;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioStreamType AUDIO_STREAM_CALL_ASSISTANT;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioStreamType AUDIO_STREAM_DTMF;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioStreamType AUDIO_STREAM_ENFORCED_AUDIBLE;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioStreamType AUDIO_STREAM_MUSIC;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioStreamType AUDIO_STREAM_NOTIFICATION;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioStreamType AUDIO_STREAM_PATCH;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioStreamType AUDIO_STREAM_REROUTING;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioStreamType AUDIO_STREAM_RING;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioStreamType AUDIO_STREAM_SYSTEM;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioStreamType AUDIO_STREAM_TTS;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioStreamType AUDIO_STREAM_VOICE_CALL;
+  }
+
+  public enum AudioUsage {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_ALARM;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_ANNOUNCEMENT;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_ASSISTANCE_SONIFICATION;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_ASSISTANT;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_CALL_ASSISTANT;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_EMERGENCY;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_GAME;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_MEDIA;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_NOTIFICATION;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_NOTIFICATION_EVENT;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_SAFETY;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_UNKNOWN;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_VEHICLE_STATUS;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_VIRTUAL_SOURCE;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_VOICE_COMMUNICATION;
+    enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
+  }
+
+  public enum DeviceCategory {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.configuration.V7_1.DeviceCategory DEVICE_CATEGORY_EARPIECE;
+    enum_constant public static final android.audio.policy.configuration.V7_1.DeviceCategory DEVICE_CATEGORY_EXT_MEDIA;
+    enum_constant public static final android.audio.policy.configuration.V7_1.DeviceCategory DEVICE_CATEGORY_HEADSET;
+    enum_constant public static final android.audio.policy.configuration.V7_1.DeviceCategory DEVICE_CATEGORY_HEARING_AID;
+    enum_constant public static final android.audio.policy.configuration.V7_1.DeviceCategory DEVICE_CATEGORY_SPEAKER;
+  }
+
+  public class DevicePorts {
+    ctor public DevicePorts();
+    method @Nullable public java.util.List<android.audio.policy.configuration.V7_1.DevicePorts.DevicePort> getDevicePort();
+  }
+
+  public static class DevicePorts.DevicePort {
+    ctor public DevicePorts.DevicePort();
+    method @Nullable public String getAddress();
+    method @Nullable public java.util.List<java.lang.String> getEncodedFormats();
+    method @Nullable public android.audio.policy.configuration.V7_1.Gains getGains();
+    method @Nullable public java.util.List<android.audio.policy.configuration.V7_1.Profile> getProfile();
+    method @Nullable public android.audio.policy.configuration.V7_1.Role getRole();
+    method @Nullable public String getTagName();
+    method @Nullable public String getType();
+    method @Nullable public boolean get_default();
+    method public void setAddress(@Nullable String);
+    method public void setEncodedFormats(@Nullable java.util.List<java.lang.String>);
+    method public void setGains(@Nullable android.audio.policy.configuration.V7_1.Gains);
+    method public void setRole(@Nullable android.audio.policy.configuration.V7_1.Role);
+    method public void setTagName(@Nullable String);
+    method public void setType(@Nullable String);
+    method public void set_default(@Nullable boolean);
+  }
+
+  public enum EngineSuffix {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.configuration.V7_1.EngineSuffix _default;
+    enum_constant public static final android.audio.policy.configuration.V7_1.EngineSuffix configurable;
+  }
+
+  public class Gains {
+    ctor public Gains();
+    method @Nullable public java.util.List<android.audio.policy.configuration.V7_1.Gains.Gain> getGain();
+  }
+
+  public static class Gains.Gain {
+    ctor public Gains.Gain();
+    method @Nullable public android.audio.policy.configuration.V7_1.AudioChannelMask getChannel_mask();
+    method @Nullable public int getDefaultValueMB();
+    method @Nullable public int getMaxRampMs();
+    method @Nullable public int getMaxValueMB();
+    method @Nullable public int getMinRampMs();
+    method @Nullable public int getMinValueMB();
+    method @Nullable public java.util.List<android.audio.policy.configuration.V7_1.AudioGainMode> getMode();
+    method @Nullable public String getName();
+    method @Nullable public int getStepValueMB();
+    method @Nullable public boolean getUseForVolume();
+    method public void setChannel_mask(@Nullable android.audio.policy.configuration.V7_1.AudioChannelMask);
+    method public void setDefaultValueMB(@Nullable int);
+    method public void setMaxRampMs(@Nullable int);
+    method public void setMaxValueMB(@Nullable int);
+    method public void setMinRampMs(@Nullable int);
+    method public void setMinValueMB(@Nullable int);
+    method public void setMode(@Nullable java.util.List<android.audio.policy.configuration.V7_1.AudioGainMode>);
+    method public void setName(@Nullable String);
+    method public void setStepValueMB(@Nullable int);
+    method public void setUseForVolume(@Nullable boolean);
+  }
+
+  public class GlobalConfiguration {
+    ctor public GlobalConfiguration();
+    method @Nullable public boolean getCall_screen_mode_supported();
+    method @Nullable public android.audio.policy.configuration.V7_1.EngineSuffix getEngine_library();
+    method @Nullable public boolean getSpeaker_drc_enabled();
+    method public void setCall_screen_mode_supported(@Nullable boolean);
+    method public void setEngine_library(@Nullable android.audio.policy.configuration.V7_1.EngineSuffix);
+    method public void setSpeaker_drc_enabled(@Nullable boolean);
+  }
+
+  public enum HalVersion {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.configuration.V7_1.HalVersion _2_0;
+    enum_constant public static final android.audio.policy.configuration.V7_1.HalVersion _3_0;
+  }
+
+  public class MixPorts {
+    ctor public MixPorts();
+    method @Nullable public java.util.List<android.audio.policy.configuration.V7_1.MixPorts.MixPort> getMixPort();
+  }
+
+  public static class MixPorts.MixPort {
+    ctor public MixPorts.MixPort();
+    method @Nullable public java.util.List<android.audio.policy.configuration.V7_1.AudioInOutFlag> getFlags();
+    method @Nullable public android.audio.policy.configuration.V7_1.Gains getGains();
+    method @Nullable public long getMaxActiveCount();
+    method @Nullable public long getMaxOpenCount();
+    method @Nullable public String getName();
+    method @Nullable public java.util.List<android.audio.policy.configuration.V7_1.AudioUsage> getPreferredUsage();
+    method @Nullable public java.util.List<android.audio.policy.configuration.V7_1.Profile> getProfile();
+    method @Nullable public long getRecommendedMuteDurationMs();
+    method @Nullable public android.audio.policy.configuration.V7_1.Role getRole();
+    method public void setFlags(@Nullable java.util.List<android.audio.policy.configuration.V7_1.AudioInOutFlag>);
+    method public void setGains(@Nullable android.audio.policy.configuration.V7_1.Gains);
+    method public void setMaxActiveCount(@Nullable long);
+    method public void setMaxOpenCount(@Nullable long);
+    method public void setName(@Nullable String);
+    method public void setPreferredUsage(@Nullable java.util.List<android.audio.policy.configuration.V7_1.AudioUsage>);
+    method public void setRecommendedMuteDurationMs(@Nullable long);
+    method public void setRole(@Nullable android.audio.policy.configuration.V7_1.Role);
+  }
+
+  public enum MixType {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.configuration.V7_1.MixType mix;
+    enum_constant public static final android.audio.policy.configuration.V7_1.MixType mux;
+  }
+
+  public class Modules {
+    ctor public Modules();
+    method @Nullable public java.util.List<android.audio.policy.configuration.V7_1.Modules.Module> getModule();
+  }
+
+  public static class Modules.Module {
+    ctor public Modules.Module();
+    method @Nullable public android.audio.policy.configuration.V7_1.AttachedDevices getAttachedDevices();
+    method @Nullable public String getDefaultOutputDevice();
+    method @Nullable public android.audio.policy.configuration.V7_1.DevicePorts getDevicePorts();
+    method @Nullable public android.audio.policy.configuration.V7_1.HalVersion getHalVersion();
+    method @Nullable public android.audio.policy.configuration.V7_1.MixPorts getMixPorts();
+    method @Nullable public String getName();
+    method @Nullable public android.audio.policy.configuration.V7_1.Routes getRoutes();
+    method public void setAttachedDevices(@Nullable android.audio.policy.configuration.V7_1.AttachedDevices);
+    method public void setDefaultOutputDevice(@Nullable String);
+    method public void setDevicePorts(@Nullable android.audio.policy.configuration.V7_1.DevicePorts);
+    method public void setHalVersion(@Nullable android.audio.policy.configuration.V7_1.HalVersion);
+    method public void setMixPorts(@Nullable android.audio.policy.configuration.V7_1.MixPorts);
+    method public void setName(@Nullable String);
+    method public void setRoutes(@Nullable android.audio.policy.configuration.V7_1.Routes);
+  }
+
+  public class Profile {
+    ctor public Profile();
+    method @Nullable public java.util.List<android.audio.policy.configuration.V7_1.AudioChannelMask> getChannelMasks();
+    method @Nullable public android.audio.policy.configuration.V7_1.AudioEncapsulationType getEncapsulationType();
+    method @Nullable public String getFormat();
+    method @Nullable public String getName();
+    method @Nullable public java.util.List<java.math.BigInteger> getSamplingRates();
+    method public void setChannelMasks(@Nullable java.util.List<android.audio.policy.configuration.V7_1.AudioChannelMask>);
+    method public void setEncapsulationType(@Nullable android.audio.policy.configuration.V7_1.AudioEncapsulationType);
+    method public void setFormat(@Nullable String);
+    method public void setName(@Nullable String);
+    method public void setSamplingRates(@Nullable java.util.List<java.math.BigInteger>);
+  }
+
+  public class Reference {
+    ctor public Reference();
+    method @Nullable public String getName();
+    method @Nullable public java.util.List<java.lang.String> getPoint();
+    method public void setName(@Nullable String);
+  }
+
+  public enum Role {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.configuration.V7_1.Role sink;
+    enum_constant public static final android.audio.policy.configuration.V7_1.Role source;
+  }
+
+  public class Routes {
+    ctor public Routes();
+    method @Nullable public java.util.List<android.audio.policy.configuration.V7_1.Routes.Route> getRoute();
+  }
+
+  public static class Routes.Route {
+    ctor public Routes.Route();
+    method @Nullable public String getSink();
+    method @Nullable public String getSources();
+    method @Nullable public android.audio.policy.configuration.V7_1.MixType getType();
+    method public void setSink(@Nullable String);
+    method public void setSources(@Nullable String);
+    method public void setType(@Nullable android.audio.policy.configuration.V7_1.MixType);
+  }
+
+  public class SurroundFormats {
+    ctor public SurroundFormats();
+    method @Nullable public java.util.List<android.audio.policy.configuration.V7_1.SurroundFormats.Format> getFormat();
+  }
+
+  public static class SurroundFormats.Format {
+    ctor public SurroundFormats.Format();
+    method @Nullable public String getName();
+    method @Nullable public java.util.List<java.lang.String> getSubformats();
+    method public void setName(@Nullable String);
+    method public void setSubformats(@Nullable java.util.List<java.lang.String>);
+  }
+
+  public class SurroundSound {
+    ctor public SurroundSound();
+    method @Nullable public android.audio.policy.configuration.V7_1.SurroundFormats getFormats();
+    method public void setFormats(@Nullable android.audio.policy.configuration.V7_1.SurroundFormats);
+  }
+
+  public enum Version {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.audio.policy.configuration.V7_1.Version _7_0;
+    enum_constant public static final android.audio.policy.configuration.V7_1.Version _7_1;
+  }
+
+  public class Volume {
+    ctor public Volume();
+    method @Nullable public android.audio.policy.configuration.V7_1.DeviceCategory getDeviceCategory();
+    method @Nullable public java.util.List<java.lang.String> getPoint();
+    method @Nullable public String getRef();
+    method @Nullable public android.audio.policy.configuration.V7_1.AudioStreamType getStream();
+    method public void setDeviceCategory(@Nullable android.audio.policy.configuration.V7_1.DeviceCategory);
+    method public void setRef(@Nullable String);
+    method public void setStream(@Nullable android.audio.policy.configuration.V7_1.AudioStreamType);
+  }
+
+  public class Volumes {
+    ctor public Volumes();
+    method @Nullable public java.util.List<android.audio.policy.configuration.V7_1.Reference> getReference();
+    method @Nullable public java.util.List<android.audio.policy.configuration.V7_1.Volume> getVolume();
+  }
+
+  public class XmlParser {
+    ctor public XmlParser();
+    method @Nullable public static android.audio.policy.configuration.V7_1.AudioPolicyConfiguration read(@NonNull java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method @Nullable public static String readText(@NonNull org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public static void skip(@NonNull org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+  }
+
+}
+
diff --git a/audio/7.1/config/api/last_current.txt b/audio/7.1/config/api/last_current.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/audio/7.1/config/api/last_current.txt
diff --git a/audio/7.1/config/api/last_removed.txt b/audio/7.1/config/api/last_removed.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/audio/7.1/config/api/last_removed.txt
diff --git a/audio/7.1/config/api/removed.txt b/audio/7.1/config/api/removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/audio/7.1/config/api/removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/audio/7.1/config/audio_policy_configuration.xsd b/audio/7.1/config/audio_policy_configuration.xsd
new file mode 100644
index 0000000..7e1da90
--- /dev/null
+++ b/audio/7.1/config/audio_policy_configuration.xsd
@@ -0,0 +1,825 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+         Licensed under the Apache License, Version 2.0 (the "License");
+         you may not use this file except in compliance with the License.
+         You may obtain a copy of the License at
+
+                    http://www.apache.org/licenses/LICENSE-2.0
+
+         Unless required by applicable law or agreed to in writing, software
+         distributed under the License is distributed on an "AS IS" BASIS,
+         WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+         See the License for the specific language governing permissions and
+         limitations under the License.
+-->
+<xs:schema version="2.0"
+           elementFormDefault="qualified"
+           attributeFormDefault="unqualified"
+           xmlns:xs="http://www.w3.org/2001/XMLSchema">
+    <!-- List the config versions supported by audio policy. -->
+    <xs:simpleType name="version">
+        <xs:restriction base="xs:decimal">
+            <xs:enumeration value="7.0"/>
+            <xs:enumeration value="7.1"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="halVersion">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                Version of the interface the hal implements. Note that this
+                relates to legacy HAL API versions since HIDL APIs are versioned
+                using other mechanisms.
+            </xs:documentation>
+        </xs:annotation>
+        <xs:restriction base="xs:decimal">
+            <!-- List of HAL versions supported by the framework. -->
+            <xs:enumeration value="2.0"/>
+            <xs:enumeration value="3.0"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:element name="audioPolicyConfiguration">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="globalConfiguration" type="globalConfiguration"/>
+                <xs:element name="modules" type="modules" maxOccurs="unbounded"/>
+                <xs:element name="volumes" type="volumes" maxOccurs="unbounded"/>
+                <xs:element name="surroundSound" type="surroundSound" minOccurs="0" />
+            </xs:sequence>
+            <xs:attribute name="version" type="version"/>
+        </xs:complexType>
+        <xs:key name="moduleNameKey">
+            <xs:selector xpath="modules/module"/>
+            <xs:field xpath="@name"/>
+        </xs:key>
+        <xs:unique name="volumeTargetUniqueness">
+            <xs:selector xpath="volumes/volume"/>
+            <xs:field xpath="@stream"/>
+            <xs:field xpath="@deviceCategory"/>
+        </xs:unique>
+        <xs:key name="volumeCurveNameKey">
+            <xs:selector xpath="volumes/reference"/>
+            <xs:field xpath="@name"/>
+        </xs:key>
+        <xs:keyref name="volumeCurveRef" refer="volumeCurveNameKey">
+            <xs:selector xpath="volumes/volume"/>
+            <xs:field xpath="@ref"/>
+        </xs:keyref>
+    </xs:element>
+    <xs:complexType name="globalConfiguration">
+        <xs:attribute name="speaker_drc_enabled" type="xs:boolean" use="required"/>
+        <xs:attribute name="call_screen_mode_supported" type="xs:boolean" use="optional"/>
+        <xs:attribute name="engine_library" type="engineSuffix" use="optional"/>
+    </xs:complexType>
+    <xs:complexType name="modules">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                There should be one section per audio HW module present on the platform.
+                Each <module/> contains two mandatory tags: “halVersion” and “name”.
+                The module "name" is the same as in previous .conf file.
+                Each module must contain the following sections:
+                 - <devicePorts/>: a list of device descriptors for all
+                   input and output devices accessible via this module.
+                   This contains both permanently attached devices and removable devices.
+                 - <mixPorts/>: listing all output and input streams exposed by the audio HAL
+                 - <routes/>: list of possible connections between input
+                   and output devices or between stream and devices.
+                   A <route/> is defined by a set of 3 attributes:
+                        -"type": mux|mix means all sources are mutual exclusive (mux) or can be mixed (mix)
+                        -"sink": the sink involved in this route
+                        -"sources": all the sources than can be connected to the sink via this route
+                 - <attachedDevices/>: permanently attached devices.
+                   The attachedDevices section is a list of devices names.
+                   Their names correspond to device names defined in "devicePorts" section.
+                 - <defaultOutputDevice/> is the device to be used when no policy rule applies
+            </xs:documentation>
+        </xs:annotation>
+        <xs:sequence>
+            <xs:element name="module" maxOccurs="unbounded">
+                <xs:complexType>
+                    <xs:sequence>
+                        <xs:element name="attachedDevices" type="attachedDevices" minOccurs="0">
+                            <xs:unique name="attachedDevicesUniqueness">
+                                <xs:selector xpath="item"/>
+                                <xs:field xpath="."/>
+                            </xs:unique>
+                        </xs:element>
+                        <xs:element name="defaultOutputDevice" type="xs:token" minOccurs="0"/>
+                        <xs:element name="mixPorts" type="mixPorts" minOccurs="0"/>
+                        <xs:element name="devicePorts" type="devicePorts" minOccurs="0"/>
+                        <xs:element name="routes" type="routes" minOccurs="0"/>
+                    </xs:sequence>
+                    <xs:attribute name="name" type="xs:string" use="required"/>
+                    <xs:attribute name="halVersion" type="halVersion" use="required"/>
+                </xs:complexType>
+                <xs:unique name="mixPortNameUniqueness">
+                    <xs:selector xpath="mixPorts/mixPort"/>
+                    <xs:field xpath="@name"/>
+                </xs:unique>
+                <xs:key name="devicePortNameKey">
+                    <xs:selector xpath="devicePorts/devicePort"/>
+                    <xs:field xpath="@tagName"/>
+                </xs:key>
+                <xs:unique name="devicePortUniqueness">
+                    <xs:selector xpath="devicePorts/devicePort"/>
+                    <xs:field xpath="@type"/>
+                    <xs:field xpath="@address"/>
+                </xs:unique>
+                <xs:keyref name="defaultOutputDeviceRef" refer="devicePortNameKey">
+                    <xs:selector xpath="defaultOutputDevice"/>
+                    <xs:field xpath="."/>
+                </xs:keyref>
+                <xs:keyref name="attachedDeviceRef" refer="devicePortNameKey">
+                    <xs:selector xpath="attachedDevices/item"/>
+                    <xs:field xpath="."/>
+                </xs:keyref>
+                <!-- The following 3 constraints try to make sure each sink port
+                     is reference in one an only one route. -->
+                <xs:key name="routeSinkKey">
+                    <!-- predicate [@type='sink'] does not work in xsd 1.0 -->
+                    <xs:selector xpath="devicePorts/devicePort|mixPorts/mixPort"/>
+                    <xs:field xpath="@tagName|@name"/>
+                </xs:key>
+                <xs:keyref name="routeSinkRef" refer="routeSinkKey">
+                    <xs:selector xpath="routes/route"/>
+                    <xs:field xpath="@sink"/>
+                </xs:keyref>
+                <xs:unique name="routeUniqueness">
+                    <xs:selector xpath="routes/route"/>
+                    <xs:field xpath="@sink"/>
+                </xs:unique>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="attachedDevices">
+        <xs:sequence>
+            <xs:element name="item" type="xs:token" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:simpleType name="audioInOutFlag">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+              The flags indicate suggested stream attributes supported by the profile.
+            </xs:documentation>
+        </xs:annotation>
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="AUDIO_OUTPUT_FLAG_DIRECT" />
+            <xs:enumeration value="AUDIO_OUTPUT_FLAG_PRIMARY" />
+            <xs:enumeration value="AUDIO_OUTPUT_FLAG_FAST" />
+            <xs:enumeration value="AUDIO_OUTPUT_FLAG_DEEP_BUFFER" />
+            <xs:enumeration value="AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD" />
+            <xs:enumeration value="AUDIO_OUTPUT_FLAG_NON_BLOCKING" />
+            <xs:enumeration value="AUDIO_OUTPUT_FLAG_HW_AV_SYNC" />
+            <xs:enumeration value="AUDIO_OUTPUT_FLAG_TTS" />
+            <xs:enumeration value="AUDIO_OUTPUT_FLAG_RAW" />
+            <xs:enumeration value="AUDIO_OUTPUT_FLAG_SYNC" />
+            <xs:enumeration value="AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO" />
+            <xs:enumeration value="AUDIO_OUTPUT_FLAG_DIRECT_PCM" />
+            <xs:enumeration value="AUDIO_OUTPUT_FLAG_MMAP_NOIRQ" />
+            <xs:enumeration value="AUDIO_OUTPUT_FLAG_VOIP_RX" />
+            <xs:enumeration value="AUDIO_OUTPUT_FLAG_INCALL_MUSIC" />
+            <xs:enumeration value="AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD" />
+            <xs:enumeration value="AUDIO_OUTPUT_FLAG_SPATIALIZER" />
+            <xs:enumeration value="AUDIO_OUTPUT_FLAG_ULTRASOUND" />
+            <xs:enumeration value="AUDIO_INPUT_FLAG_FAST" />
+            <xs:enumeration value="AUDIO_INPUT_FLAG_HW_HOTWORD" />
+            <xs:enumeration value="AUDIO_INPUT_FLAG_RAW" />
+            <xs:enumeration value="AUDIO_INPUT_FLAG_SYNC" />
+            <xs:enumeration value="AUDIO_INPUT_FLAG_MMAP_NOIRQ" />
+            <xs:enumeration value="AUDIO_INPUT_FLAG_VOIP_TX" />
+            <xs:enumeration value="AUDIO_INPUT_FLAG_HW_AV_SYNC" />
+            <xs:enumeration value="AUDIO_INPUT_FLAG_DIRECT" />
+            <xs:enumeration value="AUDIO_INPUT_FLAG_ULTRASOUND" />
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="audioInOutFlags">
+        <xs:list itemType="audioInOutFlag" />
+    </xs:simpleType>
+    <xs:simpleType name="role">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="sink"/>
+            <xs:enumeration value="source"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:complexType name="mixPorts">
+        <xs:sequence>
+            <xs:element name="mixPort" minOccurs="0" maxOccurs="unbounded">
+                <xs:complexType>
+                    <xs:sequence>
+                        <xs:element name="profile" type="profile" minOccurs="0" maxOccurs="unbounded"/>
+                        <xs:element name="gains" type="gains" minOccurs="0"/>
+                    </xs:sequence>
+                    <xs:attribute name="name" type="xs:token" use="required"/>
+                    <xs:attribute name="role" type="role" use="required"/>
+                    <xs:attribute name="flags" type="audioInOutFlags"/>
+                    <xs:attribute name="maxOpenCount" type="xs:unsignedInt"/>
+                    <xs:attribute name="maxActiveCount" type="xs:unsignedInt"/>
+                    <xs:attribute name="preferredUsage" type="audioUsageList">
+                        <xs:annotation>
+                            <xs:documentation xml:lang="en">
+                                When choosing the mixPort of an audio track, the audioPolicy
+                                first considers the mixPorts with a preferredUsage including
+                                the track AudioUsage preferred .
+                                If non support the track format, the other mixPorts are considered.
+                                Eg: a <mixPort preferredUsage="AUDIO_USAGE_MEDIA" /> will receive
+                                    the audio of all apps playing with a MEDIA usage.
+                                    It may receive audio from ALARM if there are no audio compatible
+                                    <mixPort preferredUsage="AUDIO_USAGE_ALARM" />.
+                             </xs:documentation>
+                        </xs:annotation>
+                    </xs:attribute>
+                    <xs:attribute name="recommendedMuteDurationMs" type="xs:unsignedInt"/>
+                </xs:complexType>
+                <xs:unique name="mixPortProfileUniqueness">
+                    <xs:selector xpath="profile"/>
+                    <xs:field xpath="format"/>
+                    <xs:field xpath="samplingRate"/>
+                    <xs:field xpath="channelMasks"/>
+                </xs:unique>
+                <xs:unique name="mixPortGainUniqueness">
+                    <xs:selector xpath="gains/gain"/>
+                    <xs:field xpath="@name"/>
+                </xs:unique>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:simpleType name="audioDevice">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="AUDIO_DEVICE_NONE"/>
+
+            <xs:enumeration value="AUDIO_DEVICE_OUT_EARPIECE"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_SPEAKER"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_WIRED_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_WIRED_HEADPHONE"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_SCO"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_HDMI"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_HDMI_EARC"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_AUX_DIGITAL"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_USB_ACCESSORY"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_USB_DEVICE"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_REMOTE_SUBMIX"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_TELEPHONY_TX"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_LINE"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_HDMI_ARC"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_SPDIF"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_FM"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_AUX_LINE"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_SPEAKER_SAFE"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_IP"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_BUS"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_PROXY"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_USB_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_HEARING_AID"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_ECHO_CANCELLER"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_BLE_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_BLE_SPEAKER"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_BLE_BROADCAST"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_DEFAULT"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_STUB"/>
+
+            <xs:enumeration value="AUDIO_DEVICE_IN_COMMUNICATION"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_AMBIENT"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_BUILTIN_MIC"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_WIRED_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_HDMI"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_AUX_DIGITAL"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_VOICE_CALL"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_TELEPHONY_RX"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_BACK_MIC"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_REMOTE_SUBMIX"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_USB_ACCESSORY"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_USB_DEVICE"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_FM_TUNER"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_TV_TUNER"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_LINE"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_SPDIF"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_BLUETOOTH_A2DP"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_LOOPBACK"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_IP"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_BUS"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_PROXY"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_USB_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_BLUETOOTH_BLE"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_HDMI_ARC"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_HDMI_EARC"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_ECHO_REFERENCE"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_BLE_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_DEFAULT"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_STUB"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="vendorExtension">
+        <!-- Vendor extension names must be prefixed by "VX_" to distinguish them from
+             AOSP values. Vendors must namespace their names to avoid conflicts. The
+             namespace part must only use capital latin characters and decimal digits and
+             consist of at least 3 characters. The part of the extension name after the
+             namespace may in addition include underscores. Example for a hypothetical
+             Google virtual reality device:
+
+                 <devicePort tagName="VR" type="VX_GOOGLE_VR" role="sink" />
+        -->
+        <xs:restriction base="xs:string">
+            <xs:pattern value="VX_[A-Z0-9]{3,}_[_A-Z0-9]+"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="extendableAudioDevice">
+        <xs:union memberTypes="audioDevice vendorExtension"/>
+    </xs:simpleType>
+    <xs:simpleType name="audioFormat">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="AUDIO_FORMAT_DEFAULT" />
+            <xs:enumeration value="AUDIO_FORMAT_PCM_16_BIT" />
+            <xs:enumeration value="AUDIO_FORMAT_PCM_8_BIT"/>
+            <xs:enumeration value="AUDIO_FORMAT_PCM_32_BIT"/>
+            <xs:enumeration value="AUDIO_FORMAT_PCM_8_24_BIT"/>
+            <xs:enumeration value="AUDIO_FORMAT_PCM_FLOAT"/>
+            <xs:enumeration value="AUDIO_FORMAT_PCM_24_BIT_PACKED"/>
+            <xs:enumeration value="AUDIO_FORMAT_MP3"/>
+            <xs:enumeration value="AUDIO_FORMAT_AMR_NB"/>
+            <xs:enumeration value="AUDIO_FORMAT_AMR_WB"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_MAIN"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_LC"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_SSR"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_LTP"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_HE_V1"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_SCALABLE"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ERLC"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_LD"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_HE_V2"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ELD"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_XHE"/>
+            <xs:enumeration value="AUDIO_FORMAT_HE_AAC_V1"/>
+            <xs:enumeration value="AUDIO_FORMAT_HE_AAC_V2"/>
+            <xs:enumeration value="AUDIO_FORMAT_VORBIS"/>
+            <xs:enumeration value="AUDIO_FORMAT_OPUS"/>
+            <xs:enumeration value="AUDIO_FORMAT_AC3"/>
+            <xs:enumeration value="AUDIO_FORMAT_E_AC3"/>
+            <xs:enumeration value="AUDIO_FORMAT_E_AC3_JOC"/>
+            <xs:enumeration value="AUDIO_FORMAT_DTS"/>
+            <xs:enumeration value="AUDIO_FORMAT_DTS_HD"/>
+            <xs:enumeration value="AUDIO_FORMAT_IEC61937"/>
+            <xs:enumeration value="AUDIO_FORMAT_DOLBY_TRUEHD"/>
+            <xs:enumeration value="AUDIO_FORMAT_EVRC"/>
+            <xs:enumeration value="AUDIO_FORMAT_EVRCB"/>
+            <xs:enumeration value="AUDIO_FORMAT_EVRCWB"/>
+            <xs:enumeration value="AUDIO_FORMAT_EVRCNW"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADIF"/>
+            <xs:enumeration value="AUDIO_FORMAT_WMA"/>
+            <xs:enumeration value="AUDIO_FORMAT_WMA_PRO"/>
+            <xs:enumeration value="AUDIO_FORMAT_AMR_WB_PLUS"/>
+            <xs:enumeration value="AUDIO_FORMAT_MP2"/>
+            <xs:enumeration value="AUDIO_FORMAT_QCELP"/>
+            <xs:enumeration value="AUDIO_FORMAT_DSD"/>
+            <xs:enumeration value="AUDIO_FORMAT_FLAC"/>
+            <xs:enumeration value="AUDIO_FORMAT_ALAC"/>
+            <xs:enumeration value="AUDIO_FORMAT_APE"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_MAIN"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_LC"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_SSR"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_LTP"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_HE_V1"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_SCALABLE"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_ERLC"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_LD"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_HE_V2"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_ELD"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_XHE"/>
+            <xs:enumeration value="AUDIO_FORMAT_SBC"/>
+            <xs:enumeration value="AUDIO_FORMAT_APTX"/>
+            <xs:enumeration value="AUDIO_FORMAT_APTX_HD"/>
+            <xs:enumeration value="AUDIO_FORMAT_AC4"/>
+            <xs:enumeration value="AUDIO_FORMAT_LDAC"/>
+            <xs:enumeration value="AUDIO_FORMAT_MAT"/>
+            <xs:enumeration value="AUDIO_FORMAT_MAT_1_0"/>
+            <xs:enumeration value="AUDIO_FORMAT_MAT_2_0"/>
+            <xs:enumeration value="AUDIO_FORMAT_MAT_2_1"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_LATM"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_LATM_LC"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_LATM_HE_V1"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_LATM_HE_V2"/>
+            <xs:enumeration value="AUDIO_FORMAT_CELT"/>
+            <xs:enumeration value="AUDIO_FORMAT_APTX_ADAPTIVE"/>
+            <xs:enumeration value="AUDIO_FORMAT_LHDC"/>
+            <xs:enumeration value="AUDIO_FORMAT_LHDC_LL"/>
+            <xs:enumeration value="AUDIO_FORMAT_APTX_TWSP"/>
+            <xs:enumeration value="AUDIO_FORMAT_LC3"/>
+            <xs:enumeration value="AUDIO_FORMAT_MPEGH_BL_L3"/>
+            <xs:enumeration value="AUDIO_FORMAT_MPEGH_BL_L4"/>
+            <xs:enumeration value="AUDIO_FORMAT_MPEGH_LC_L3"/>
+            <xs:enumeration value="AUDIO_FORMAT_MPEGH_LC_L4"/>
+            <xs:enumeration value="AUDIO_FORMAT_IEC60958"/>
+            <xs:enumeration value="AUDIO_FORMAT_DTS_UHD"/>
+            <xs:enumeration value="AUDIO_FORMAT_DRA"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="extendableAudioFormat">
+        <xs:union memberTypes="audioFormat vendorExtension"/>
+    </xs:simpleType>
+    <xs:simpleType name="audioUsage">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                Audio usage specifies the intended use case for the sound being played.
+                Please consult frameworks/base/media/java/android/media/AudioAttributes.java
+                for the description of each value.
+            </xs:documentation>
+        </xs:annotation>
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="AUDIO_USAGE_UNKNOWN" />
+            <xs:enumeration value="AUDIO_USAGE_MEDIA" />
+            <xs:enumeration value="AUDIO_USAGE_VOICE_COMMUNICATION" />
+            <xs:enumeration value="AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING" />
+            <xs:enumeration value="AUDIO_USAGE_ALARM" />
+            <xs:enumeration value="AUDIO_USAGE_NOTIFICATION" />
+            <xs:enumeration value="AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE" />
+            <xs:enumeration value="AUDIO_USAGE_NOTIFICATION_EVENT" />
+            <xs:enumeration value="AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY" />
+            <xs:enumeration value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE" />
+            <xs:enumeration value="AUDIO_USAGE_ASSISTANCE_SONIFICATION" />
+            <xs:enumeration value="AUDIO_USAGE_GAME" />
+            <xs:enumeration value="AUDIO_USAGE_VIRTUAL_SOURCE" />
+            <xs:enumeration value="AUDIO_USAGE_ASSISTANT" />
+            <xs:enumeration value="AUDIO_USAGE_CALL_ASSISTANT" />
+            <xs:enumeration value="AUDIO_USAGE_EMERGENCY" />
+            <xs:enumeration value="AUDIO_USAGE_SAFETY" />
+            <xs:enumeration value="AUDIO_USAGE_VEHICLE_STATUS" />
+            <xs:enumeration value="AUDIO_USAGE_ANNOUNCEMENT" />
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="audioUsageList">
+        <xs:list itemType="audioUsage"/>
+    </xs:simpleType>
+    <xs:simpleType name="audioContentType">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                Audio content type expresses the general category of the content.
+                Please consult frameworks/base/media/java/android/media/AudioAttributes.java
+                for the description of each value.
+            </xs:documentation>
+        </xs:annotation>
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="AUDIO_CONTENT_TYPE_UNKNOWN"/>
+            <xs:enumeration value="AUDIO_CONTENT_TYPE_SPEECH"/>
+            <xs:enumeration value="AUDIO_CONTENT_TYPE_MUSIC"/>
+            <xs:enumeration value="AUDIO_CONTENT_TYPE_MOVIE"/>
+            <xs:enumeration value="AUDIO_CONTENT_TYPE_SONIFICATION"/>
+            <xs:enumeration value="AUDIO_CONTENT_TYPE_ULTRASOUND"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="samplingRates">
+        <xs:list itemType="xs:nonNegativeInteger" />
+    </xs:simpleType>
+    <xs:simpleType name="audioChannelMask">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                Audio channel mask specifies presence of particular channels.
+                There are two representations:
+                - representation position (traditional discrete channel specification,
+                  e.g. "left", "right");
+                - indexed (this is similar to "tracks" in audio mixing, channels
+                  are represented using numbers).
+            </xs:documentation>
+        </xs:annotation>
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="AUDIO_CHANNEL_NONE"/>
+            <xs:enumeration value="AUDIO_CHANNEL_OUT_MONO"/>
+            <xs:enumeration value="AUDIO_CHANNEL_OUT_STEREO"/>
+            <xs:enumeration value="AUDIO_CHANNEL_OUT_2POINT1"/>
+            <xs:enumeration value="AUDIO_CHANNEL_OUT_TRI"/>
+            <xs:enumeration value="AUDIO_CHANNEL_OUT_TRI_BACK"/>
+            <xs:enumeration value="AUDIO_CHANNEL_OUT_3POINT1"/>
+            <xs:enumeration value="AUDIO_CHANNEL_OUT_2POINT0POINT2"/>
+            <xs:enumeration value="AUDIO_CHANNEL_OUT_2POINT1POINT2"/>
+            <xs:enumeration value="AUDIO_CHANNEL_OUT_3POINT0POINT2"/>
+            <xs:enumeration value="AUDIO_CHANNEL_OUT_3POINT1POINT2"/>
+            <xs:enumeration value="AUDIO_CHANNEL_OUT_QUAD"/>
+            <xs:enumeration value="AUDIO_CHANNEL_OUT_QUAD_BACK"/>
+            <xs:enumeration value="AUDIO_CHANNEL_OUT_QUAD_SIDE"/>
+            <xs:enumeration value="AUDIO_CHANNEL_OUT_SURROUND"/>
+            <xs:enumeration value="AUDIO_CHANNEL_OUT_PENTA"/>
+            <xs:enumeration value="AUDIO_CHANNEL_OUT_5POINT1"/>
+            <xs:enumeration value="AUDIO_CHANNEL_OUT_5POINT1_BACK"/>
+            <xs:enumeration value="AUDIO_CHANNEL_OUT_5POINT1_SIDE"/>
+            <xs:enumeration value="AUDIO_CHANNEL_OUT_5POINT1POINT2"/>
+            <xs:enumeration value="AUDIO_CHANNEL_OUT_5POINT1POINT4"/>
+            <xs:enumeration value="AUDIO_CHANNEL_OUT_6POINT1"/>
+            <xs:enumeration value="AUDIO_CHANNEL_OUT_7POINT1"/>
+            <xs:enumeration value="AUDIO_CHANNEL_OUT_7POINT1POINT2"/>
+            <xs:enumeration value="AUDIO_CHANNEL_OUT_7POINT1POINT4"/>
+            <xs:enumeration value="AUDIO_CHANNEL_OUT_9POINT1POINT4"/>
+            <xs:enumeration value="AUDIO_CHANNEL_OUT_9POINT1POINT6"/>
+            <xs:enumeration value="AUDIO_CHANNEL_OUT_13POINT_360RA"/>
+            <xs:enumeration value="AUDIO_CHANNEL_OUT_22POINT2"/>
+            <xs:enumeration value="AUDIO_CHANNEL_OUT_MONO_HAPTIC_A"/>
+            <xs:enumeration value="AUDIO_CHANNEL_OUT_STEREO_HAPTIC_A"/>
+            <xs:enumeration value="AUDIO_CHANNEL_OUT_HAPTIC_AB"/>
+            <xs:enumeration value="AUDIO_CHANNEL_OUT_MONO_HAPTIC_AB"/>
+            <xs:enumeration value="AUDIO_CHANNEL_OUT_STEREO_HAPTIC_AB"/>
+            <xs:enumeration value="AUDIO_CHANNEL_IN_MONO"/>
+            <xs:enumeration value="AUDIO_CHANNEL_IN_STEREO"/>
+            <xs:enumeration value="AUDIO_CHANNEL_IN_FRONT_BACK"/>
+            <xs:enumeration value="AUDIO_CHANNEL_IN_6"/>
+            <xs:enumeration value="AUDIO_CHANNEL_IN_2POINT0POINT2"/>
+            <xs:enumeration value="AUDIO_CHANNEL_IN_2POINT1POINT2"/>
+            <xs:enumeration value="AUDIO_CHANNEL_IN_3POINT0POINT2"/>
+            <xs:enumeration value="AUDIO_CHANNEL_IN_3POINT1POINT2"/>
+            <xs:enumeration value="AUDIO_CHANNEL_IN_5POINT1"/>
+            <xs:enumeration value="AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO"/>
+            <xs:enumeration value="AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO"/>
+            <xs:enumeration value="AUDIO_CHANNEL_IN_VOICE_CALL_MONO"/>
+            <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_1"/>
+            <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_2"/>
+            <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_3"/>
+            <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_4"/>
+            <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_5"/>
+            <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_6"/>
+            <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_7"/>
+            <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_8"/>
+            <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_9"/>
+            <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_10"/>
+            <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_11"/>
+            <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_12"/>
+            <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_13"/>
+            <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_14"/>
+            <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_15"/>
+            <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_16"/>
+            <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_17"/>
+            <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_18"/>
+            <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_19"/>
+            <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_20"/>
+            <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_21"/>
+            <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_22"/>
+            <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_23"/>
+            <xs:enumeration value="AUDIO_CHANNEL_INDEX_MASK_24"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="channelMasks">
+        <xs:list itemType="audioChannelMask" />
+    </xs:simpleType>
+    <xs:simpleType name="audioEncapsulationType">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="AUDIO_ENCAPSULATION_TYPE_NONE"/>
+            <xs:enumeration value="AUDIO_ENCAPSULATION_TYPE_IEC61937"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:complexType name="profile">
+        <xs:attribute name="name" type="xs:token" use="optional"/>
+        <xs:attribute name="format" type="extendableAudioFormat" use="optional"/>
+        <xs:attribute name="samplingRates" type="samplingRates" use="optional"/>
+        <xs:attribute name="channelMasks" type="channelMasks" use="optional"/>
+        <xs:attribute name="encapsulationType" type="audioEncapsulationType" use="optional"/>
+    </xs:complexType>
+    <xs:simpleType name="audioGainMode">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="AUDIO_GAIN_MODE_JOINT"/>
+            <xs:enumeration value="AUDIO_GAIN_MODE_CHANNELS"/>
+            <xs:enumeration value="AUDIO_GAIN_MODE_RAMP"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="audioGainModeMaskUnrestricted">
+        <xs:list itemType="audioGainMode" />
+    </xs:simpleType>
+    <xs:simpleType name='audioGainModeMask'>
+        <xs:restriction base='audioGainModeMaskUnrestricted'>
+            <xs:minLength value='1' />
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:complexType name="gains">
+        <xs:sequence>
+            <xs:element name="gain" minOccurs="0" maxOccurs="unbounded">
+                <xs:complexType>
+                    <xs:attribute name="name" type="xs:token" use="required"/>
+                    <xs:attribute name="mode" type="audioGainModeMask" use="required"/>
+                    <xs:attribute name="channel_mask" type="audioChannelMask" use="optional"/>
+                    <xs:attribute name="minValueMB" type="xs:int" use="optional"/>
+                    <xs:attribute name="maxValueMB" type="xs:int" use="optional"/>
+                    <xs:attribute name="defaultValueMB" type="xs:int" use="optional"/>
+                    <xs:attribute name="stepValueMB" type="xs:int" use="optional"/>
+                    <xs:attribute name="minRampMs" type="xs:int" use="optional"/>
+                    <xs:attribute name="maxRampMs" type="xs:int" use="optional"/>
+                    <xs:attribute name="useForVolume" type="xs:boolean" use="optional"/>
+                </xs:complexType>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="devicePorts">
+        <xs:sequence>
+            <xs:element name="devicePort" minOccurs="0" maxOccurs="unbounded">
+                <xs:complexType>
+                    <xs:sequence>
+                        <xs:element name="profile" type="profile" minOccurs="0" maxOccurs="unbounded"/>
+                        <xs:element name="gains" type="gains" minOccurs="0"/>
+                    </xs:sequence>
+                    <xs:attribute name="tagName" type="xs:token" use="required"/>
+                    <xs:attribute name="type" type="extendableAudioDevice" use="required"/>
+                    <xs:attribute name="role" type="role" use="required"/>
+                    <xs:attribute name="address" type="xs:string" use="optional" default=""/>
+                    <!-- Note that XSD 1.0 can not check that a type only has one default. -->
+                    <xs:attribute name="default" type="xs:boolean" use="optional">
+                        <xs:annotation>
+                            <xs:documentation xml:lang="en">
+                                The default device will be used if multiple have the same type
+                                and no explicit route request exists for a specific device of
+                                that type.
+                            </xs:documentation>
+                        </xs:annotation>
+                    </xs:attribute>
+                    <xs:attribute name="encodedFormats" type="audioFormatsList" use="optional"
+                                  default="" />
+                </xs:complexType>
+                <xs:unique name="devicePortProfileUniqueness">
+                    <xs:selector xpath="profile"/>
+                    <xs:field xpath="format"/>
+                    <xs:field xpath="samplingRate"/>
+                    <xs:field xpath="channelMasks"/>
+                </xs:unique>
+                <xs:unique name="devicePortGainUniqueness">
+                    <xs:selector xpath="gains/gain"/>
+                    <xs:field xpath="@name"/>
+                </xs:unique>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:simpleType name="mixType">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="mix"/>
+            <xs:enumeration value="mux"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:complexType name="routes">
+        <xs:sequence>
+            <xs:element name="route" minOccurs="0" maxOccurs="unbounded">
+                <xs:annotation>
+                    <xs:documentation xml:lang="en">
+                        List all available sources for a given sink.
+                    </xs:documentation>
+                </xs:annotation>
+                <xs:complexType>
+                    <xs:attribute name="type" type="mixType" use="required"/>
+                    <xs:attribute name="sink" type="xs:string" use="required"/>
+                    <xs:attribute name="sources" type="xs:string" use="required"/>
+                </xs:complexType>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="volumes">
+        <xs:sequence>
+            <xs:element name="volume" type="volume" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="reference" type="reference" minOccurs="0" maxOccurs="unbounded">
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+    <!-- TODO: Always require a ref for better xsd validations.
+               Currently a volume could have no points nor ref
+               as it can not be forbidden by xsd 1.0.-->
+    <xs:simpleType name="volumePoint">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                Comma separated pair of number.
+                The fist one is the framework level (between 0 and 100).
+                The second one is the volume to send to the HAL.
+                The framework will interpolate volumes not specified.
+                Their MUST be at least 2 points specified.
+            </xs:documentation>
+        </xs:annotation>
+        <xs:restriction base="xs:string">
+            <xs:pattern value="([0-9]{1,2}|100),-?[0-9]+"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="audioStreamType">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                Audio stream type describing the intended use case of a stream.
+                Please consult frameworks/base/media/java/android/media/AudioSystem.java
+                for the description of each value.
+            </xs:documentation>
+        </xs:annotation>
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="AUDIO_STREAM_VOICE_CALL"/>
+            <xs:enumeration value="AUDIO_STREAM_SYSTEM"/>
+            <xs:enumeration value="AUDIO_STREAM_RING"/>
+            <xs:enumeration value="AUDIO_STREAM_MUSIC"/>
+            <xs:enumeration value="AUDIO_STREAM_ALARM"/>
+            <xs:enumeration value="AUDIO_STREAM_NOTIFICATION"/>
+            <xs:enumeration value="AUDIO_STREAM_BLUETOOTH_SCO"/>
+            <xs:enumeration value="AUDIO_STREAM_ENFORCED_AUDIBLE"/>
+            <xs:enumeration value="AUDIO_STREAM_DTMF"/>
+            <xs:enumeration value="AUDIO_STREAM_TTS"/>
+            <xs:enumeration value="AUDIO_STREAM_ACCESSIBILITY"/>
+            <xs:enumeration value="AUDIO_STREAM_ASSISTANT"/>
+            <xs:enumeration value="AUDIO_STREAM_REROUTING"/>
+            <xs:enumeration value="AUDIO_STREAM_PATCH"/>
+            <xs:enumeration value="AUDIO_STREAM_CALL_ASSISTANT"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="audioSource">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                An audio source defines the intended use case for the sound being recorded.
+                Please consult frameworks/base/media/java/android/media/MediaRecorder.java
+                for the description of each value.
+            </xs:documentation>
+        </xs:annotation>
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="AUDIO_SOURCE_DEFAULT"/>
+            <xs:enumeration value="AUDIO_SOURCE_MIC"/>
+            <xs:enumeration value="AUDIO_SOURCE_VOICE_UPLINK"/>
+            <xs:enumeration value="AUDIO_SOURCE_VOICE_DOWNLINK"/>
+            <xs:enumeration value="AUDIO_SOURCE_VOICE_CALL"/>
+            <xs:enumeration value="AUDIO_SOURCE_CAMCORDER"/>
+            <xs:enumeration value="AUDIO_SOURCE_VOICE_RECOGNITION"/>
+            <xs:enumeration value="AUDIO_SOURCE_VOICE_COMMUNICATION"/>
+            <xs:enumeration value="AUDIO_SOURCE_REMOTE_SUBMIX"/>
+            <xs:enumeration value="AUDIO_SOURCE_UNPROCESSED"/>
+            <xs:enumeration value="AUDIO_SOURCE_VOICE_PERFORMANCE"/>
+            <xs:enumeration value="AUDIO_SOURCE_ECHO_REFERENCE"/>
+            <xs:enumeration value="AUDIO_SOURCE_FM_TUNER"/>
+            <xs:enumeration value="AUDIO_SOURCE_HOTWORD"/>
+            <xs:enumeration value="AUDIO_SOURCE_ULTRASOUND"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <!-- Enum values of device_category from Volume.h. -->
+    <xs:simpleType name="deviceCategory">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="DEVICE_CATEGORY_HEADSET"/>
+            <xs:enumeration value="DEVICE_CATEGORY_SPEAKER"/>
+            <xs:enumeration value="DEVICE_CATEGORY_EARPIECE"/>
+            <xs:enumeration value="DEVICE_CATEGORY_EXT_MEDIA"/>
+            <xs:enumeration value="DEVICE_CATEGORY_HEARING_AID"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:complexType name="volume">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                Volume section defines a volume curve for a given use case and device category.
+                It contains a list of points of this curve expressing the attenuation in Millibels
+                for a given volume index from 0 to 100.
+                <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_SPEAKER">
+                    <point>0,-9600</point>
+                    <point>100,0</point>
+                </volume>
+
+                It may also reference a reference/@name to avoid duplicating curves.
+                <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_SPEAKER"
+                        ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
+                <reference name="DEFAULT_MEDIA_VOLUME_CURVE">
+                    <point>0,-9600</point>
+                    <point>100,0</point>
+                </reference>
+            </xs:documentation>
+        </xs:annotation>
+        <xs:sequence>
+            <xs:element name="point" type="volumePoint" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+        <xs:attribute name="stream" type="audioStreamType"/>
+        <xs:attribute name="deviceCategory" type="deviceCategory"/>
+        <xs:attribute name="ref" type="xs:token" use="optional"/>
+    </xs:complexType>
+    <xs:complexType name="reference">
+        <xs:sequence>
+            <xs:element name="point" type="volumePoint" minOccurs="2" maxOccurs="unbounded"/>
+        </xs:sequence>
+        <xs:attribute name="name" type="xs:token" use="required"/>
+    </xs:complexType>
+    <xs:complexType name="surroundSound">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                Surround Sound section provides configuration related to handling of
+                multi-channel formats.
+            </xs:documentation>
+        </xs:annotation>
+        <xs:sequence>
+            <xs:element name="formats" type="surroundFormats"/>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:simpleType name="audioFormatsList">
+        <xs:list itemType="extendableAudioFormat" />
+    </xs:simpleType>
+    <xs:complexType name="surroundFormats">
+        <xs:sequence>
+            <xs:element name="format" minOccurs="0" maxOccurs="unbounded">
+                <xs:complexType>
+                    <xs:attribute name="name" type="extendableAudioFormat" use="required"/>
+                    <xs:attribute name="subformats" type="audioFormatsList" />
+                </xs:complexType>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:simpleType name="engineSuffix">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="default"/>
+            <xs:enumeration value="configurable"/>
+        </xs:restriction>
+    </xs:simpleType>
+</xs:schema>
diff --git a/audio/7.1/types.hal b/audio/7.1/types.hal
new file mode 100644
index 0000000..9d8ee4d
--- /dev/null
+++ b/audio/7.1/types.hal
@@ -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.audio@7.1;
+
+/**
+ * Latency modes used for the variable latency feature on output streams.
+ * Used by setLatencyMode() and getRecommendedLatencyModes() methods.
+ */
+
+@export(name="audio_latency_mode_t", value_prefix="AUDIO_LATENCY_MODE_")
+enum LatencyMode : int32_t {
+    /** No specific constraint on the latency */
+    FREE = 0,
+    /** A relatively low latency compatible with head tracking operation (e.g less than 100ms) */
+    LOW = 1,
+};
diff --git a/audio/aidl/Android.bp b/audio/aidl/Android.bp
new file mode 100644
index 0000000..6a0cfa5
--- /dev/null
+++ b/audio/aidl/Android.bp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+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.audio.common",
+    vendor_available: true,
+    srcs: [
+        "android/hardware/audio/common/PlaybackTrackMetadata.aidl",
+        "android/hardware/audio/common/RecordTrackMetadata.aidl",
+        "android/hardware/audio/common/SinkMetadata.aidl",
+        "android/hardware/audio/common/SourceMetadata.aidl",
+    ],
+    imports: [
+        "android.media.audio.common.types",
+    ],
+    stability: "vintf",
+    backend: {
+        cpp: {
+            enabled: true,
+        },
+        java: {
+            platform_apis: true,
+        },
+        ndk: {
+            vndk: {
+                enabled: true,
+            },
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.bluetooth",
+            ],
+            min_sdk_version: "31",
+        },
+    },
+    versions: [
+    ],
+}
diff --git a/audio/aidl/OWNERS b/audio/aidl/OWNERS
new file mode 100644
index 0000000..f9a2d6b
--- /dev/null
+++ b/audio/aidl/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 48436
+elaurent@google.com
+mnaganov@google.com
diff --git a/audio/aidl/aidl_api/android.hardware.audio.common/current/android/hardware/audio/common/PlaybackTrackMetadata.aidl b/audio/aidl/aidl_api/android.hardware.audio.common/current/android/hardware/audio/common/PlaybackTrackMetadata.aidl
new file mode 100644
index 0000000..8fe8696
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.common/current/android/hardware/audio/common/PlaybackTrackMetadata.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.common;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable PlaybackTrackMetadata {
+  android.media.audio.common.AudioUsage usage = android.media.audio.common.AudioUsage.INVALID;
+  android.media.audio.common.AudioContentType contentType = android.media.audio.common.AudioContentType.UNKNOWN;
+  float gain;
+  @utf8InCpp String[] tags;
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.common/current/android/hardware/audio/common/RecordTrackMetadata.aidl b/audio/aidl/aidl_api/android.hardware.audio.common/current/android/hardware/audio/common/RecordTrackMetadata.aidl
new file mode 100644
index 0000000..50330ef
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.common/current/android/hardware/audio/common/RecordTrackMetadata.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.common;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable RecordTrackMetadata {
+  android.media.audio.common.AudioSource source = android.media.audio.common.AudioSource.SYS_RESERVED_INVALID;
+  float gain;
+  @utf8InCpp String[] tags;
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.common/current/android/hardware/audio/common/SinkMetadata.aidl b/audio/aidl/aidl_api/android.hardware.audio.common/current/android/hardware/audio/common/SinkMetadata.aidl
new file mode 100644
index 0000000..270147d
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.common/current/android/hardware/audio/common/SinkMetadata.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.common;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable SinkMetadata {
+  android.hardware.audio.common.RecordTrackMetadata[] tracks;
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.common/current/android/hardware/audio/common/SourceMetadata.aidl b/audio/aidl/aidl_api/android.hardware.audio.common/current/android/hardware/audio/common/SourceMetadata.aidl
new file mode 100644
index 0000000..2d4a982
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.common/current/android/hardware/audio/common/SourceMetadata.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.common;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable SourceMetadata {
+  android.hardware.audio.common.PlaybackTrackMetadata[] tracks;
+}
diff --git a/audio/aidl/android/hardware/audio/common/PlaybackTrackMetadata.aidl b/audio/aidl/android/hardware/audio/common/PlaybackTrackMetadata.aidl
new file mode 100644
index 0000000..28a2f32
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/common/PlaybackTrackMetadata.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.common;
+
+import android.media.audio.common.AudioContentType;
+import android.media.audio.common.AudioUsage;
+
+/**
+ * Metadata of a playback track for an output stream.
+ */
+@JavaDerive(equals=true, toString=true)
+@VintfStability
+parcelable PlaybackTrackMetadata {
+    AudioUsage usage = AudioUsage.INVALID;
+    AudioContentType contentType = AudioContentType.UNKNOWN;
+    /**
+     * Non-negative linear gain (scaling) applied to track samples.
+     * 0 means muted, 1 is unity gain, 2 means double amplitude, etc.
+     */
+    float gain;
+    /**
+     * Tags from AudioTrack audio attributes. Tag is an additional use case
+     * qualifier complementing AudioUsage and AudioContentType. Tags are set by
+     * vendor specific applications and must be prefixed by "VX_". Vendor must
+     * namespace their tag names to avoid conflicts, for example:
+     * "VX_GOOGLE_VR". At least 3 characters are required for the vendor
+     * namespace.
+     */
+    @utf8InCpp String[] tags;
+}
diff --git a/audio/aidl/android/hardware/audio/common/RecordTrackMetadata.aidl b/audio/aidl/android/hardware/audio/common/RecordTrackMetadata.aidl
new file mode 100644
index 0000000..9a59b41
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/common/RecordTrackMetadata.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.common;
+
+import android.media.audio.common.AudioSource;
+
+/**
+ * Metadata of a record track for an input stream.
+ */
+@JavaDerive(equals=true, toString=true)
+@VintfStability
+parcelable RecordTrackMetadata {
+    AudioSource source = AudioSource.SYS_RESERVED_INVALID;
+    /**
+     * Non-negative linear gain (scaling) applied to track samples.
+     * 0 means muted, 1 is unity gain, 2 means double amplitude, etc.
+     */
+    float gain;
+    /**
+     * Tags from AudioRecord audio attributes. Tag is an additional use case
+     * qualifier complementing AudioUsage and AudioContentType. Tags are set by
+     * vendor specific applications and must be prefixed by "VX_". Vendor must
+     * namespace their tag names to avoid conflicts, for example:
+     * "VX_GOOGLE_VR". At least 3 characters are required for the vendor
+     * namespace.
+     */
+    @utf8InCpp String[] tags;
+}
diff --git a/audio/aidl/android/hardware/audio/common/SinkMetadata.aidl b/audio/aidl/android/hardware/audio/common/SinkMetadata.aidl
new file mode 100644
index 0000000..188c847
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/common/SinkMetadata.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.common;
+
+import android.hardware.audio.common.RecordTrackMetadata;
+
+/**
+ * Metadata of record tracks for an input stream.
+ */
+@JavaDerive(equals=true, toString=true)
+@VintfStability
+parcelable SinkMetadata {
+    RecordTrackMetadata[] tracks;
+}
diff --git a/audio/aidl/android/hardware/audio/common/SourceMetadata.aidl b/audio/aidl/android/hardware/audio/common/SourceMetadata.aidl
new file mode 100644
index 0000000..e9f23c6
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/common/SourceMetadata.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.common;
+
+import android.hardware.audio.common.PlaybackTrackMetadata;
+
+/**
+ * Metadata of playback tracks for an output stream.
+ */
+@JavaDerive(equals=true, toString=true)
+@VintfStability
+parcelable SourceMetadata {
+    PlaybackTrackMetadata[] tracks;
+}
diff --git a/audio/common/7.1/Android.bp b/audio/common/7.1/Android.bp
new file mode 100644
index 0000000..a257510
--- /dev/null
+++ b/audio/common/7.1/Android.bp
@@ -0,0 +1,23 @@
+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.audio.common@7.1-enums",
+    vendor_available: true,
+    generated_headers: ["audio_policy_configuration_V7_1_enums"],
+    generated_sources: ["audio_policy_configuration_V7_1_enums"],
+    header_libs: ["libxsdc-utils"],
+    export_generated_headers: ["audio_policy_configuration_V7_1_enums"],
+    export_header_lib_headers: ["libxsdc-utils"],
+    export_include_dirs: ["enums/include"],
+    shared_libs: [
+        "libbase",
+        "liblog",
+    ],
+}
diff --git a/audio/common/7.1/enums/OWNERS b/audio/common/7.1/enums/OWNERS
new file mode 100644
index 0000000..24071af
--- /dev/null
+++ b/audio/common/7.1/enums/OWNERS
@@ -0,0 +1,2 @@
+elaurent@google.com
+mnaganov@google.com
diff --git a/audio/common/7.1/enums/include/android_audio_policy_configuration_V7_1-enums.h b/audio/common/7.1/enums/include/android_audio_policy_configuration_V7_1-enums.h
new file mode 100644
index 0000000..6f6a0ca
--- /dev/null
+++ b/audio/common/7.1/enums/include/android_audio_policy_configuration_V7_1-enums.h
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_AUDIO_POLICY_CONFIGURATION_V7_1__ENUMS_H
+#define ANDROID_AUDIO_POLICY_CONFIGURATION_V7_1__ENUMS_H
+
+#include <sys/types.h>
+#include <regex>
+#include <string>
+
+#include <android_audio_policy_configuration_V7_1_enums.h>
+
+namespace android::audio::policy::configuration::V7_1 {
+
+static inline size_t getChannelCount(AudioChannelMask mask) {
+    switch (mask) {
+        case AudioChannelMask::AUDIO_CHANNEL_NONE:
+            return 0;
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_MONO:
+        case AudioChannelMask::AUDIO_CHANNEL_IN_MONO:
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_1:
+            return 1;
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO:
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_MONO_HAPTIC_A:
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_HAPTIC_AB:
+        case AudioChannelMask::AUDIO_CHANNEL_IN_STEREO:
+        case AudioChannelMask::AUDIO_CHANNEL_IN_FRONT_BACK:
+        case AudioChannelMask::AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO:
+        case AudioChannelMask::AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO:
+        case AudioChannelMask::AUDIO_CHANNEL_IN_VOICE_CALL_MONO:
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_2:
+            return 2;
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_2POINT1:
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO_HAPTIC_A:
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_MONO_HAPTIC_AB:
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_TRI:
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_TRI_BACK:
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_3:
+            return 3;
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_2POINT0POINT2:
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_3POINT1:
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_QUAD:
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_QUAD_BACK:
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_QUAD_SIDE:
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_SURROUND:
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO_HAPTIC_AB:
+        case AudioChannelMask::AUDIO_CHANNEL_IN_2POINT0POINT2:
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_4:
+            return 4;
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_2POINT1POINT2:
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_3POINT0POINT2:
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_PENTA:
+        case AudioChannelMask::AUDIO_CHANNEL_IN_2POINT1POINT2:
+        case AudioChannelMask::AUDIO_CHANNEL_IN_3POINT0POINT2:
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_5:
+            return 5;
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_3POINT1POINT2:
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_5POINT1:
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_5POINT1_BACK:
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_5POINT1_SIDE:
+        case AudioChannelMask::AUDIO_CHANNEL_IN_6:
+        case AudioChannelMask::AUDIO_CHANNEL_IN_3POINT1POINT2:
+        case AudioChannelMask::AUDIO_CHANNEL_IN_5POINT1:
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_6:
+            return 6;
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_6POINT1:
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_7:
+            return 7;
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_5POINT1POINT2:
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_7POINT1:
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_8:
+            return 8;
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_9:
+            return 9;
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_5POINT1POINT4:
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_7POINT1POINT2:
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_10:
+            return 10;
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_11:
+            return 11;
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_7POINT1POINT4:
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_12:
+            return 12;
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_13POINT_360RA:
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_13:
+            return 13;
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_9POINT1POINT4:
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_14:
+            return 14;
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_15:
+            return 15;
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_9POINT1POINT6:
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_16:
+            return 16;
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_17:
+            return 17;
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_18:
+            return 18;
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_19:
+            return 19;
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_20:
+            return 20;
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_21:
+            return 21;
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_22:
+            return 22;
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_23:
+            return 23;
+        case AudioChannelMask::AUDIO_CHANNEL_OUT_22POINT2:
+        case AudioChannelMask::AUDIO_CHANNEL_INDEX_MASK_24:
+            return 24;
+        case AudioChannelMask::UNKNOWN:
+            return 0;
+            // No default to make sure all cases are covered.
+    }
+    // This is to avoid undefined behavior if 'mask' isn't a valid enum value.
+    return 0;
+}
+
+static inline ssize_t getChannelCount(const std::string& mask) {
+    return getChannelCount(stringToAudioChannelMask(mask));
+}
+
+static inline bool isOutputDevice(AudioDevice device) {
+    switch (device) {
+        case AudioDevice::UNKNOWN:
+        case AudioDevice::AUDIO_DEVICE_NONE:
+            return false;
+        case AudioDevice::AUDIO_DEVICE_OUT_EARPIECE:
+        case AudioDevice::AUDIO_DEVICE_OUT_SPEAKER:
+        case AudioDevice::AUDIO_DEVICE_OUT_WIRED_HEADSET:
+        case AudioDevice::AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
+        case AudioDevice::AUDIO_DEVICE_OUT_BLUETOOTH_SCO:
+        case AudioDevice::AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
+        case AudioDevice::AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT:
+        case AudioDevice::AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
+        case AudioDevice::AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
+        case AudioDevice::AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:
+        case AudioDevice::AUDIO_DEVICE_OUT_AUX_DIGITAL:
+        case AudioDevice::AUDIO_DEVICE_OUT_HDMI:
+        case AudioDevice::AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET:
+        case AudioDevice::AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET:
+        case AudioDevice::AUDIO_DEVICE_OUT_USB_ACCESSORY:
+        case AudioDevice::AUDIO_DEVICE_OUT_USB_DEVICE:
+        case AudioDevice::AUDIO_DEVICE_OUT_REMOTE_SUBMIX:
+        case AudioDevice::AUDIO_DEVICE_OUT_TELEPHONY_TX:
+        case AudioDevice::AUDIO_DEVICE_OUT_LINE:
+        case AudioDevice::AUDIO_DEVICE_OUT_HDMI_ARC:
+        case AudioDevice::AUDIO_DEVICE_OUT_HDMI_EARC:
+        case AudioDevice::AUDIO_DEVICE_OUT_SPDIF:
+        case AudioDevice::AUDIO_DEVICE_OUT_FM:
+        case AudioDevice::AUDIO_DEVICE_OUT_AUX_LINE:
+        case AudioDevice::AUDIO_DEVICE_OUT_SPEAKER_SAFE:
+        case AudioDevice::AUDIO_DEVICE_OUT_IP:
+        case AudioDevice::AUDIO_DEVICE_OUT_BUS:
+        case AudioDevice::AUDIO_DEVICE_OUT_PROXY:
+        case AudioDevice::AUDIO_DEVICE_OUT_USB_HEADSET:
+        case AudioDevice::AUDIO_DEVICE_OUT_HEARING_AID:
+        case AudioDevice::AUDIO_DEVICE_OUT_ECHO_CANCELLER:
+        case AudioDevice::AUDIO_DEVICE_OUT_BLE_HEADSET:
+        case AudioDevice::AUDIO_DEVICE_OUT_BLE_SPEAKER:
+        case AudioDevice::AUDIO_DEVICE_OUT_BLE_BROADCAST:
+        case AudioDevice::AUDIO_DEVICE_OUT_DEFAULT:
+        case AudioDevice::AUDIO_DEVICE_OUT_STUB:
+            return true;
+        case AudioDevice::AUDIO_DEVICE_IN_COMMUNICATION:
+        case AudioDevice::AUDIO_DEVICE_IN_AMBIENT:
+        case AudioDevice::AUDIO_DEVICE_IN_BUILTIN_MIC:
+        case AudioDevice::AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET:
+        case AudioDevice::AUDIO_DEVICE_IN_WIRED_HEADSET:
+        case AudioDevice::AUDIO_DEVICE_IN_AUX_DIGITAL:
+        case AudioDevice::AUDIO_DEVICE_IN_HDMI:
+        case AudioDevice::AUDIO_DEVICE_IN_VOICE_CALL:
+        case AudioDevice::AUDIO_DEVICE_IN_TELEPHONY_RX:
+        case AudioDevice::AUDIO_DEVICE_IN_BACK_MIC:
+        case AudioDevice::AUDIO_DEVICE_IN_REMOTE_SUBMIX:
+        case AudioDevice::AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET:
+        case AudioDevice::AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET:
+        case AudioDevice::AUDIO_DEVICE_IN_USB_ACCESSORY:
+        case AudioDevice::AUDIO_DEVICE_IN_USB_DEVICE:
+        case AudioDevice::AUDIO_DEVICE_IN_FM_TUNER:
+        case AudioDevice::AUDIO_DEVICE_IN_TV_TUNER:
+        case AudioDevice::AUDIO_DEVICE_IN_LINE:
+        case AudioDevice::AUDIO_DEVICE_IN_SPDIF:
+        case AudioDevice::AUDIO_DEVICE_IN_BLUETOOTH_A2DP:
+        case AudioDevice::AUDIO_DEVICE_IN_LOOPBACK:
+        case AudioDevice::AUDIO_DEVICE_IN_IP:
+        case AudioDevice::AUDIO_DEVICE_IN_BUS:
+        case AudioDevice::AUDIO_DEVICE_IN_PROXY:
+        case AudioDevice::AUDIO_DEVICE_IN_USB_HEADSET:
+        case AudioDevice::AUDIO_DEVICE_IN_BLUETOOTH_BLE:
+        case AudioDevice::AUDIO_DEVICE_IN_HDMI_ARC:
+        case AudioDevice::AUDIO_DEVICE_IN_HDMI_EARC:
+        case AudioDevice::AUDIO_DEVICE_IN_ECHO_REFERENCE:
+        case AudioDevice::AUDIO_DEVICE_IN_BLE_HEADSET:
+        case AudioDevice::AUDIO_DEVICE_IN_DEFAULT:
+        case AudioDevice::AUDIO_DEVICE_IN_STUB:
+            return false;
+            // No default to make sure all cases are covered.
+    }
+    // This is to avoid undefined behavior if 'device' isn't a valid enum value.
+    return false;
+}
+
+static inline bool isOutputDevice(const std::string& device) {
+    return isOutputDevice(stringToAudioDevice(device));
+}
+
+static inline bool isTelephonyDevice(AudioDevice device) {
+    return device == AudioDevice::AUDIO_DEVICE_OUT_TELEPHONY_TX ||
+           device == AudioDevice::AUDIO_DEVICE_IN_TELEPHONY_RX;
+}
+
+static inline bool isTelephonyDevice(const std::string& device) {
+    return isTelephonyDevice(stringToAudioDevice(device));
+}
+
+static inline bool maybeVendorExtension(const std::string& s) {
+    // Only checks whether the string starts with the "vendor prefix".
+    static const std::string vendorPrefix = "VX_";
+    return s.size() > vendorPrefix.size() && s.substr(0, vendorPrefix.size()) == vendorPrefix;
+}
+
+static inline bool isVendorExtension(const std::string& s) {
+    // Must be the same as the "vendorExtension" rule from the XSD file.
+    static const std::regex vendorExtension("VX_[A-Z0-9]{3,}_[_A-Z0-9]+");
+    return std::regex_match(s.begin(), s.end(), vendorExtension);
+}
+
+static inline bool isUnknownAudioChannelMask(const std::string& mask) {
+    return stringToAudioChannelMask(mask) == AudioChannelMask::UNKNOWN;
+}
+
+static inline bool isUnknownAudioContentType(const std::string& contentType) {
+    return stringToAudioContentType(contentType) == AudioContentType::UNKNOWN;
+}
+
+static inline bool isUnknownAudioDevice(const std::string& device) {
+    return stringToAudioDevice(device) == AudioDevice::UNKNOWN && !isVendorExtension(device);
+}
+
+static inline bool isUnknownAudioFormat(const std::string& format) {
+    return stringToAudioFormat(format) == AudioFormat::UNKNOWN && !isVendorExtension(format);
+}
+
+static inline bool isUnknownAudioGainMode(const std::string& mode) {
+    return stringToAudioGainMode(mode) == AudioGainMode::UNKNOWN;
+}
+
+static inline bool isUnknownAudioInOutFlag(const std::string& flag) {
+    return stringToAudioInOutFlag(flag) == AudioInOutFlag::UNKNOWN;
+}
+
+static inline bool isUnknownAudioSource(const std::string& source) {
+    return stringToAudioSource(source) == AudioSource::UNKNOWN;
+}
+
+static inline bool isUnknownAudioStreamType(const std::string& streamType) {
+    return stringToAudioStreamType(streamType) == AudioStreamType::UNKNOWN;
+}
+
+static inline bool isUnknownAudioUsage(const std::string& usage) {
+    return stringToAudioUsage(usage) == AudioUsage::UNKNOWN;
+}
+
+static inline bool isLinearPcm(AudioFormat format) {
+    switch (format) {
+        case AudioFormat::AUDIO_FORMAT_PCM_16_BIT:
+        case AudioFormat::AUDIO_FORMAT_PCM_8_BIT:
+        case AudioFormat::AUDIO_FORMAT_PCM_32_BIT:
+        case AudioFormat::AUDIO_FORMAT_PCM_8_24_BIT:
+        case AudioFormat::AUDIO_FORMAT_PCM_FLOAT:
+        case AudioFormat::AUDIO_FORMAT_PCM_24_BIT_PACKED:
+            return true;
+        default:
+            return false;
+    }
+}
+
+static inline bool isLinearPcm(const std::string& format) {
+    return isLinearPcm(stringToAudioFormat(format));
+}
+
+static inline bool isUnknownAudioEncapsulationType(const std::string& encapsulationType) {
+    return stringToAudioEncapsulationType(encapsulationType) == AudioEncapsulationType::UNKNOWN;
+}
+
+}  // namespace android::audio::policy::configuration::V7_1
+
+#endif  // ANDROID_AUDIO_POLICY_CONFIGURATION_V7_1__ENUMS_H
diff --git a/audio/common/all-versions/default/7.0/HidlUtils.cpp b/audio/common/all-versions/default/7.0/HidlUtils.cpp
index 5a5b5d2..0fd2947 100644
--- a/audio/common/all-versions/default/7.0/HidlUtils.cpp
+++ b/audio/common/all-versions/default/7.0/HidlUtils.cpp
@@ -21,7 +21,7 @@
 #define LOG_TAG "HidlUtils"
 #include <log/log.h>
 
-#include <android_audio_policy_configuration_V7_0-enums.h>
+#include PATH(APM_XSD_ENUMS_H_FILENAME)
 #include <common/all-versions/HidlSupport.h>
 #include <common/all-versions/VersionUtils.h>
 
@@ -31,11 +31,11 @@
 namespace hardware {
 namespace audio {
 namespace common {
-namespace CPP_VERSION {
+namespace COMMON_TYPES_CPP_VERSION {
 namespace implementation {
 
 namespace xsd {
-using namespace ::android::audio::policy::configuration::V7_0;
+using namespace ::android::audio::policy::configuration::CPP_VERSION;
 }
 
 #define CONVERT_CHECKED(expr, result)                   \
@@ -485,8 +485,12 @@
 status_t HidlUtils::audioUsageFromHal(audio_usage_t halUsage, AudioUsage* usage) {
     if (halUsage == AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST ||
         halUsage == AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT ||
+#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
+        halUsage == AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED) {
+#else
         halUsage == AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED ||
         halUsage == AUDIO_USAGE_NOTIFICATION_EVENT) {
+#endif
         halUsage = AUDIO_USAGE_NOTIFICATION;
     }
     *usage = audio_usage_to_string(halUsage);
@@ -1151,7 +1155,7 @@
 }
 
 }  // namespace implementation
-}  // namespace CPP_VERSION
+}  // namespace COMMON_TYPES_CPP_VERSION
 }  // namespace common
 }  // namespace audio
 }  // namespace hardware
diff --git a/audio/common/all-versions/default/Android.bp b/audio/common/all-versions/default/Android.bp
index 8f55744..9543674 100644
--- a/audio/common/all-versions/default/Android.bp
+++ b/audio/common/all-versions/default/Android.bp
@@ -157,6 +157,28 @@
     ],
 }
 
+cc_library {
+    name: "android.hardware.audio.common@7.1-util",
+    defaults: ["android.hardware.audio.common-util_default"],
+    srcs: [
+        "7.0/HidlUtils.cpp",
+        "HidlUtilsCommon.cpp",
+        "UuidUtils.cpp",
+    ],
+    shared_libs: [
+        "android.hardware.audio.common@7.0",
+        "android.hardware.audio.common@7.1-enums",
+        "libbase",
+    ],
+    cflags: [
+        "-DMAJOR_VERSION=7",
+        "-DMINOR_VERSION=1",
+        "-DCOMMON_TYPES_MINOR_VERSION=0",
+        "-DCORE_TYPES_MINOR_VERSION=0",
+        "-include common/all-versions/VersionMacro.h",
+    ],
+}
+
 // Note: this isn't a VTS test, but rather a unit test
 // to verify correctness of conversion utilities.
 cc_test {
@@ -189,6 +211,8 @@
     name: "android.hardware.audio.common@7.0-util_tests",
     defaults: ["android.hardware.audio.common-util_default"],
 
+    tidy_timeout_srcs: ["tests/hidlutils_tests.cpp"],
+
     srcs: ["tests/hidlutils_tests.cpp"],
 
     // Use static linking to allow running in presubmit on
@@ -214,3 +238,37 @@
 
     test_suites: ["device-tests"],
 }
+
+cc_test {
+    name: "android.hardware.audio.common@7.1-util_tests",
+    defaults: ["android.hardware.audio.common-util_default"],
+
+    tidy_timeout_srcs: ["tests/hidlutils_tests.cpp"],
+
+    srcs: ["tests/hidlutils_tests.cpp"],
+
+    // Use static linking to allow running in presubmit on
+    // targets that don't have HAL V7.1.
+    static_libs: [
+        "android.hardware.audio.common@7.1-enums",
+        "android.hardware.audio.common@7.1-util",
+        "android.hardware.audio.common@7.0",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "libxml2",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+        "-DMAJOR_VERSION=7",
+        "-DMINOR_VERSION=1",
+        "-DCOMMON_TYPES_MINOR_VERSION=0",
+        "-DCORE_TYPES_MINOR_VERSION=0",
+        "-include common/all-versions/VersionMacro.h",
+    ],
+
+    test_suites: ["device-tests"],
+}
diff --git a/audio/common/all-versions/default/HidlUtils.h b/audio/common/all-versions/default/HidlUtils.h
index 98ecc07..ad9dee2 100644
--- a/audio/common/all-versions/default/HidlUtils.h
+++ b/audio/common/all-versions/default/HidlUtils.h
@@ -17,7 +17,9 @@
 #ifndef android_hardware_audio_Hidl_Utils_H_
 #define android_hardware_audio_Hidl_Utils_H_
 
-#include PATH(android/hardware/audio/common/FILE_VERSION/types.h)
+// clang-format off
+#include PATH(android/hardware/audio/common/COMMON_TYPES_FILE_VERSION/types.h)
+// clang-format on
 
 #include <memory>
 #include <string>
@@ -29,11 +31,11 @@
 namespace hardware {
 namespace audio {
 namespace common {
-namespace CPP_VERSION {
+namespace COMMON_TYPES_CPP_VERSION {
 namespace implementation {
 
 using ::android::hardware::hidl_vec;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
 
 struct HidlUtils {
     static status_t audioConfigFromHal(const audio_config_t& halConfig, bool isInput,
@@ -267,7 +269,7 @@
 #endif  // MAJOR_VERSION <= 6
 
 }  // namespace implementation
-}  // namespace CPP_VERSION
+}  // namespace COMMON_TYPES_CPP_VERSION
 }  // namespace common
 }  // namespace audio
 }  // namespace hardware
diff --git a/audio/common/all-versions/default/HidlUtilsCommon.cpp b/audio/common/all-versions/default/HidlUtilsCommon.cpp
index d2da193..bc3d870 100644
--- a/audio/common/all-versions/default/HidlUtilsCommon.cpp
+++ b/audio/common/all-versions/default/HidlUtilsCommon.cpp
@@ -20,7 +20,7 @@
 namespace hardware {
 namespace audio {
 namespace common {
-namespace CPP_VERSION {
+namespace COMMON_TYPES_CPP_VERSION {
 namespace implementation {
 
 status_t HidlUtils::audioPortConfigsFromHal(unsigned int numHalConfigs,
@@ -51,7 +51,7 @@
 }
 
 }  // namespace implementation
-}  // namespace CPP_VERSION
+}  // namespace COMMON_TYPES_CPP_VERSION
 }  // namespace common
 }  // namespace audio
 }  // namespace hardware
diff --git a/audio/common/all-versions/default/TEST_MAPPING b/audio/common/all-versions/default/TEST_MAPPING
index c965113..780beea 100644
--- a/audio/common/all-versions/default/TEST_MAPPING
+++ b/audio/common/all-versions/default/TEST_MAPPING
@@ -5,6 +5,9 @@
     },
     {
       "name": "android.hardware.audio.common@7.0-util_tests"
+    },
+    {
+      "name": "android.hardware.audio.common@7.1-util_tests"
     }
   ]
 }
diff --git a/audio/common/all-versions/default/UuidUtils.h b/audio/common/all-versions/default/UuidUtils.h
index cd04fb0..4a64f0a 100644
--- a/audio/common/all-versions/default/UuidUtils.h
+++ b/audio/common/all-versions/default/UuidUtils.h
@@ -20,7 +20,7 @@
 #include <string>
 
 // clang-format off
-#include PATH(android/hardware/audio/common/FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/common/COMMON_TYPES_FILE_VERSION/types.h)
 // clang-format on
 
 #include <system/audio.h>
@@ -32,7 +32,7 @@
 namespace CPP_VERSION {
 namespace implementation {
 
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
 
 class UuidUtils {
   public:
diff --git a/audio/common/all-versions/default/VersionUtils.h b/audio/common/all-versions/default/VersionUtils.h
index 9bfca0c..9771374 100644
--- a/audio/common/all-versions/default/VersionUtils.h
+++ b/audio/common/all-versions/default/VersionUtils.h
@@ -17,7 +17,30 @@
 #ifndef ANDROID_HARDWARE_AUDIO_EFFECT_VERSION_UTILS_H
 #define ANDROID_HARDWARE_AUDIO_EFFECT_VERSION_UTILS_H
 
-#include PATH(android/hardware/audio/common/FILE_VERSION/types.h)
+// A workaround for b/216149583 (vendor code having its own copy of VersionMacro.h)
+#ifndef COMMON_TYPES_MINOR_VERSION
+#define COMMON_TYPES_MINOR_VERSION MINOR_VERSION
+#endif
+#ifndef CORE_TYPES_MINOR_VERSION
+#define CORE_TYPES_MINOR_VERSION MINOR_VERSION
+#endif
+#ifndef COMMON_TYPES_FILE_VERSION
+#define COMMON_TYPES_FILE_VERSION EXPAND_CONCAT_3(MAJOR_VERSION, ., COMMON_TYPES_MINOR_VERSION)
+#endif
+#ifndef CORE_TYPES_FILE_VERSION
+#define CORE_TYPES_FILE_VERSION EXPAND_CONCAT_3(MAJOR_VERSION, ., CORE_TYPES_MINOR_VERSION)
+#endif
+#ifndef COMMON_TYPES_CPP_VERSION
+#define COMMON_TYPES_CPP_VERSION EXPAND_CONCAT_4(V, MAJOR_VERSION, _, COMMON_TYPES_MINOR_VERSION)
+#endif
+#ifndef CORE_TYPES_CPP_VERSION
+#define CORE_TYPES_CPP_VERSION EXPAND_CONCAT_4(V, MAJOR_VERSION, _, CORE_TYPES_MINOR_VERSION)
+#endif
+// End of workaround
+
+// clang-format off
+#include PATH(android/hardware/audio/common/COMMON_TYPES_FILE_VERSION/types.h)
+// clang-format on
 
 namespace android {
 namespace hardware {
diff --git a/audio/common/all-versions/default/service/Android.bp b/audio/common/all-versions/default/service/Android.bp
index 0d4775c6a..9890be2 100644
--- a/audio/common/all-versions/default/service/Android.bp
+++ b/audio/common/all-versions/default/service/Android.bp
@@ -7,17 +7,40 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
+soong_config_module_type {
+    name: "android_hardware_audio_config_default",
+    module_type: "cc_defaults",
+    config_namespace: "android_hardware_audio",
+    bool_variables: [
+        "run_64bit",
+    ],
+    properties: ["compile_multilib"],
+}
+
+android_hardware_audio_config_default {
+    name: "android_hardware_audio_config_defaults",
+
+    soong_config_variables: {
+        run_64bit: {
+            conditions_default: {
+                // Prefer 32 bit as the binary must always be installed at the same
+                // location for init to start it and the build system does not support
+                // having two binaries installable to the same location even if they are
+                // not installed in the same build.
+                compile_multilib: "prefer32",
+            },
+            compile_multilib: "64",
+        },
+    },
+}
+
 cc_binary {
     name: "android.hardware.audio.service",
 
     init_rc: ["android.hardware.audio.service.rc"],
     relative_install_path: "hw",
     vendor: true,
-    // Prefer 32 bit as the binary must always be installed at the same
-    // location for init to start it and the build system does not support
-    // having two binaries installable to the same location even if they are
-    // not installed in the same build.
-    compile_multilib: "prefer32",
+
     srcs: ["service.cpp"],
 
     cflags: [
@@ -29,11 +52,16 @@
     shared_libs: [
         "libcutils",
         "libbinder",
+        "libbinder_ndk",
         "libhidlbase",
         "liblog",
         "libutils",
         "libhardware",
     ],
+
+    defaults: [
+        "android_hardware_audio_config_defaults",
+    ],
 }
 
 // Legacy service name, use android.hardware.audio.service instead
diff --git a/audio/common/all-versions/default/service/service.cpp b/audio/common/all-versions/default/service/service.cpp
index bbc14ad..fbf6165 100644
--- a/audio/common/all-versions/default/service/service.cpp
+++ b/audio/common/all-versions/default/service/service.cpp
@@ -16,11 +16,14 @@
 
 #define LOG_TAG "audiohalservice"
 
+#include <signal.h>
 #include <string>
 #include <vector>
 
+#include <android/binder_process.h>
 #include <binder/ProcessState.h>
 #include <cutils/properties.h>
+#include <dlfcn.h>
 #include <hidl/HidlTransportSupport.h>
 #include <hidl/LegacySupport.h>
 #include <hwbinder/ProcessState.h>
@@ -44,11 +47,41 @@
     return false;
 }
 
+static bool registerExternalServiceImplementation(const std::string& libName,
+                                                  const std::string& funcName) {
+    constexpr int dlMode = RTLD_LAZY;
+    void* handle = nullptr;
+    dlerror();  // clear
+    auto libPath = libName + ".so";
+    handle = dlopen(libPath.c_str(), dlMode);
+    if (handle == nullptr) {
+        const char* error = dlerror();
+        ALOGE("Failed to dlopen %s: %s", libPath.c_str(),
+              error != nullptr ? error : "unknown error");
+        return false;
+    }
+    binder_status_t (*factoryFunction)();
+    *(void**)(&factoryFunction) = dlsym(handle, funcName.c_str());
+    if (!factoryFunction) {
+        const char* error = dlerror();
+        ALOGE("Factory function %s not found in libName %s: %s", funcName.c_str(), libPath.c_str(),
+              error != nullptr ? error : "unknown error");
+        dlclose(handle);
+        return false;
+    }
+    return ((*factoryFunction)() == STATUS_OK);
+}
+
 int main(int /* argc */, char* /* argv */ []) {
+    signal(SIGPIPE, SIG_IGN);
+
     ::android::ProcessState::initWithDriver("/dev/vndbinder");
     // start a threadpool for vndbinder interactions
     ::android::ProcessState::self()->startThreadPool();
 
+    ABinderProcess_setThreadPoolMaxThreadCount(1);
+    ABinderProcess_startThreadPool();
+
     const int32_t defaultValue = -1;
     int32_t value =
         property_get_int32("persist.vendor.audio.service.hwbinder.size_kbyte", defaultValue);
@@ -63,6 +96,7 @@
     const std::vector<InterfacesList> mandatoryInterfaces = {
         {
             "Audio Core API",
+            "android.hardware.audio@7.1::IDevicesFactory",
             "android.hardware.audio@7.0::IDevicesFactory",
             "android.hardware.audio@6.0::IDevicesFactory",
             "android.hardware.audio@5.0::IDevicesFactory",
@@ -87,6 +121,7 @@
         },
         {
             "Bluetooth Audio API",
+            "android.hardware.bluetooth.audio@2.2::IBluetoothAudioProvidersFactory",
             "android.hardware.bluetooth.audio@2.1::IBluetoothAudioProvidersFactory",
             "android.hardware.bluetooth.audio@2.0::IBluetoothAudioProvidersFactory",
         },
@@ -96,6 +131,13 @@
             "android.hardware.bluetooth.a2dp@1.0::IBluetoothAudioOffload"
         }
     };
+
+    const std::vector<std::pair<std::string,std::string>> optionalInterfaceSharedLibs = {
+        {
+            "android.hardware.bluetooth.audio-impl",
+            "createIBluetoothAudioProviderFactory",
+        },
+    };
     // clang-format on
 
     for (const auto& listIter : mandatoryInterfaces) {
@@ -112,5 +154,15 @@
                  "Could not register %s", interfaceFamilyName.c_str());
     }
 
+    for (const auto& interfacePair : optionalInterfaceSharedLibs) {
+        const std::string& libraryName = interfacePair.first;
+        const std::string& interfaceLoaderFuncName = interfacePair.second;
+        if (registerExternalServiceImplementation(libraryName, interfaceLoaderFuncName)) {
+            ALOGI("%s() from %s success", interfaceLoaderFuncName.c_str(), libraryName.c_str());
+        } else {
+            ALOGW("%s() from %s failed", interfaceLoaderFuncName.c_str(), libraryName.c_str());
+        }
+    }
+
     joinRpcThreadpool();
 }
diff --git a/audio/common/all-versions/default/tests/hidlutils6_tests.cpp b/audio/common/all-versions/default/tests/hidlutils6_tests.cpp
index 3a24e75..ca59b9d 100644
--- a/audio/common/all-versions/default/tests/hidlutils6_tests.cpp
+++ b/audio/common/all-versions/default/tests/hidlutils6_tests.cpp
@@ -23,14 +23,14 @@
 #include <system/audio.h>
 
 using namespace android;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
-using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::HidlUtils;
 
 // Not generated automatically because DeviceAddress contains
 // an union.
 //
 // operator== must be defined in the same namespace as the data type.
-namespace android::hardware::audio::common::CPP_VERSION {
+namespace android::hardware::audio::common::COMMON_TYPES_CPP_VERSION {
 
 inline bool operator==(const DeviceAddress& lhs, const DeviceAddress& rhs) {
     if (lhs.device != rhs.device) return false;
@@ -49,7 +49,7 @@
     return lhs.busAddress == rhs.busAddress;
 }
 
-}  // namespace android::hardware::audio::common::CPP_VERSION
+}  // namespace android::hardware::audio::common::COMMON_TYPES_CPP_VERSION
 
 static void ConvertDeviceAddress(const DeviceAddress& device) {
     audio_devices_t halDeviceType;
diff --git a/audio/common/all-versions/default/tests/hidlutils_tests.cpp b/audio/common/all-versions/default/tests/hidlutils_tests.cpp
index c9e6fac..e5ed844 100644
--- a/audio/common/all-versions/default/tests/hidlutils_tests.cpp
+++ b/audio/common/all-versions/default/tests/hidlutils_tests.cpp
@@ -17,22 +17,23 @@
 #include <array>
 #include <string>
 
+#include <android-base/test_utils.h>
 #include <gtest/gtest.h>
 
 #define LOG_TAG "HidlUtils_Test"
 #include <log/log.h>
 
 #include <HidlUtils.h>
-#include <android_audio_policy_configuration_V7_0-enums.h>
+#include PATH(APM_XSD_ENUMS_H_FILENAME)
 #include <system/audio.h>
 #include <xsdc/XsdcSupport.h>
 
 using namespace android;
 using ::android::hardware::hidl_vec;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
-using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::HidlUtils;
 namespace xsd {
-using namespace ::android::audio::policy::configuration::V7_0;
+using namespace ::android::audio::policy::configuration::CPP_VERSION;
 }
 
 static constexpr audio_channel_mask_t kInvalidHalChannelMask = AUDIO_CHANNEL_INVALID;
@@ -1100,6 +1101,7 @@
 TYPED_TEST_SUITE(FilterTest, FilterTestTypeParams);
 
 TYPED_TEST(FilterTest, FilterOutNonVendorTags) {
+    SKIP_WITH_HWASAN; // b/230535046
     TypeParam emptyTags;
     EXPECT_EQ(emptyTags, HidlUtils::filterOutNonVendorTags(emptyTags));
 
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/common/all-versions/util/include/common/all-versions/VersionMacro.h b/audio/common/all-versions/util/include/common/all-versions/VersionMacro.h
index dc54cee..875e167 100644
--- a/audio/common/all-versions/util/include/common/all-versions/VersionMacro.h
+++ b/audio/common/all-versions/util/include/common/all-versions/VersionMacro.h
@@ -21,6 +21,14 @@
 #error "MAJOR_VERSION and MINOR_VERSION must be defined"
 #endif
 
+#ifndef COMMON_TYPES_MINOR_VERSION
+#define COMMON_TYPES_MINOR_VERSION MINOR_VERSION
+#endif
+
+#ifndef CORE_TYPES_MINOR_VERSION
+#define CORE_TYPES_MINOR_VERSION MINOR_VERSION
+#endif
+
 /** Allows macro expansion for x and add surrounding `<>`.
  * Is intended to be used for version dependant includes as
  * `#include` do not macro expand if starting with < or "
@@ -34,10 +42,30 @@
 #define EXPAND_CONCAT_3(a, b, c) CONCAT_3(a, b, c)
 /** The directory name of the version: <major>.<minor> */
 #define FILE_VERSION EXPAND_CONCAT_3(MAJOR_VERSION, ., MINOR_VERSION)
+#define COMMON_TYPES_FILE_VERSION EXPAND_CONCAT_3(MAJOR_VERSION, ., COMMON_TYPES_MINOR_VERSION)
+#define CORE_TYPES_FILE_VERSION EXPAND_CONCAT_3(MAJOR_VERSION, ., CORE_TYPES_MINOR_VERSION)
 
 #define CONCAT_4(a, b, c, d) a##b##c##d
 #define EXPAND_CONCAT_4(a, b, c, d) CONCAT_4(a, b, c, d)
 /** The c++ namespace of the version: V<major>_<minor> */
 #define CPP_VERSION EXPAND_CONCAT_4(V, MAJOR_VERSION, _, MINOR_VERSION)
+#define COMMON_TYPES_CPP_VERSION EXPAND_CONCAT_4(V, MAJOR_VERSION, _, COMMON_TYPES_MINOR_VERSION)
+#define CORE_TYPES_CPP_VERSION EXPAND_CONCAT_4(V, MAJOR_VERSION, _, CORE_TYPES_MINOR_VERSION)
+
+/* Gluing these file names from macros is non-trivial due to "illegal tokens"
+   occurring during expansion. The XSD and enums always use the minor version. */
+// clang-format off
+#if MAJOR_VERSION >= 7
+#if MINOR_VERSION == 0
+#define APM_XSD_H_FILENAME android_audio_policy_configuration_V7_0.h
+#define APM_XSD_ENUMS_H_FILENAME android_audio_policy_configuration_V7_0-enums.h
+#elif MINOR_VERSION == 1
+#define APM_XSD_H_FILENAME android_audio_policy_configuration_V7_1.h
+#define APM_XSD_ENUMS_H_FILENAME android_audio_policy_configuration_V7_1-enums.h
+#else
+#error "Unsupported minor version"
+#endif
+#endif
+// clang-format on
 
 #endif  // ANDROID_HARDWARE_VERSION_MACRO_H
diff --git a/audio/core/all-versions/OWNERS b/audio/core/all-versions/OWNERS
index 6fdc97c..f9a2d6b 100644
--- a/audio/core/all-versions/OWNERS
+++ b/audio/core/all-versions/OWNERS
@@ -1,3 +1,3 @@
+# Bug component: 48436
 elaurent@google.com
-krocard@google.com
 mnaganov@google.com
diff --git a/audio/core/all-versions/default/Android.bp b/audio/core/all-versions/default/Android.bp
index b170ff4..3536561 100644
--- a/audio/core/all-versions/default/Android.bp
+++ b/audio/core/all-versions/default/Android.bp
@@ -57,7 +57,6 @@
     header_libs: [
         "android.hardware.audio-impl_headers",
         "android.hardware.audio.common.util@all-versions",
-        "libaudioclient_headers",
         "libaudioutils_headers",
         "libaudio_system_headers",
         "libhardware_headers",
@@ -162,3 +161,29 @@
     name: "android.hardware.audio@7.0-impl",
     defaults: ["android.hardware.audio@7.0-impl_default"],
 }
+
+cc_defaults {
+    name: "android.hardware.audio@7.1-impl_default",
+    defaults: ["android.hardware.audio-impl_default"],
+    shared_libs: [
+        "android.hardware.audio@7.0",
+        "android.hardware.audio@7.1",
+        "android.hardware.audio@7.1-util",
+        "android.hardware.audio.common@7.0",
+        "android.hardware.audio.common@7.1-enums",
+        "android.hardware.audio.common@7.1-util",
+        "libbase",
+    ],
+    cflags: [
+        "-DMAJOR_VERSION=7",
+        "-DMINOR_VERSION=1",
+        "-DCOMMON_TYPES_MINOR_VERSION=0",
+        "-DCORE_TYPES_MINOR_VERSION=0",
+        "-include common/all-versions/VersionMacro.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.audio@7.1-impl",
+    defaults: ["android.hardware.audio@7.1-impl_default"],
+}
diff --git a/audio/core/all-versions/default/Device.cpp b/audio/core/all-versions/default/Device.cpp
index c33e6f3..b954fcd 100644
--- a/audio/core/all-versions/default/Device.cpp
+++ b/audio/core/all-versions/default/Device.cpp
@@ -41,7 +41,10 @@
 namespace CPP_VERSION {
 namespace implementation {
 
-using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::HidlUtils;
+namespace util {
+using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION::implementation::util;
+}
 
 Device::Device(audio_hw_device_t* device) : mIsClosed(false), mDevice(device) {}
 
@@ -84,7 +87,7 @@
     if (mDevice->set_master_volume == NULL) {
         return Result::NOT_SUPPORTED;
     }
-    if (!isGainNormalized(volume)) {
+    if (!util::isGainNormalized(volume)) {
         ALOGW("Can not set a master volume (%f) outside [0,1]", volume);
         return Result::INVALID_ARGUMENTS;
     }
@@ -150,7 +153,7 @@
     return Void();
 }
 
-std::tuple<Result, sp<IStreamOut>> Device::openOutputStreamImpl(int32_t ioHandle,
+std::tuple<Result, sp<IStreamOut>> Device::openOutputStreamCore(int32_t ioHandle,
                                                                 const DeviceAddress& device,
                                                                 const AudioConfig& config,
                                                                 const AudioOutputFlags& flags,
@@ -187,7 +190,7 @@
     return {analyzeStatus("open_output_stream", status, {EINVAL} /*ignore*/), streamOut};
 }
 
-std::tuple<Result, sp<IStreamIn>> Device::openInputStreamImpl(
+std::tuple<Result, sp<IStreamIn>> Device::openInputStreamCore(
         int32_t ioHandle, const DeviceAddress& device, const AudioConfig& config,
         const AudioInputFlags& flags, AudioSource source, AudioConfig* suggestedConfig) {
     audio_config_t halConfig;
@@ -230,7 +233,7 @@
                                       openOutputStream_cb _hidl_cb) {
     AudioConfig suggestedConfig;
     auto [result, streamOut] =
-        openOutputStreamImpl(ioHandle, device, config, flags, &suggestedConfig);
+            openOutputStreamCore(ioHandle, device, config, flags, &suggestedConfig);
     _hidl_cb(result, streamOut, suggestedConfig);
     return Void();
 }
@@ -240,12 +243,36 @@
                                      AudioSource source, openInputStream_cb _hidl_cb) {
     AudioConfig suggestedConfig;
     auto [result, streamIn] =
-        openInputStreamImpl(ioHandle, device, config, flags, source, &suggestedConfig);
+            openInputStreamCore(ioHandle, device, config, flags, source, &suggestedConfig);
     _hidl_cb(result, streamIn, suggestedConfig);
     return Void();
 }
 
 #elif MAJOR_VERSION >= 4
+std::tuple<Result, sp<IStreamOut>, AudioConfig> Device::openOutputStreamImpl(
+        int32_t ioHandle, const DeviceAddress& device, const AudioConfig& config,
+        const SourceMetadata& sourceMetadata,
+#if MAJOR_VERSION <= 6
+        AudioOutputFlags flags) {
+    if (status_t status = CoreUtils::sourceMetadataToHal(sourceMetadata, nullptr);
+        status != NO_ERROR) {
+#else
+        const AudioOutputFlags& flags) {
+    if (status_t status = CoreUtils::sourceMetadataToHalV7(sourceMetadata,
+                                                           false /*ignoreNonVendorTags*/, nullptr);
+        status != NO_ERROR) {
+#endif
+        return {analyzeStatus("sourceMetadataToHal", status), nullptr, {}};
+    }
+    AudioConfig suggestedConfig;
+    auto [result, streamOut] =
+            openOutputStreamCore(ioHandle, device, config, flags, &suggestedConfig);
+    if (streamOut) {
+        streamOut->updateSourceMetadata(sourceMetadata);
+    }
+    return {result, streamOut, suggestedConfig};
+}
+
 Return<void> Device::openOutputStream(int32_t ioHandle, const DeviceAddress& device,
                                       const AudioConfig& config,
 #if MAJOR_VERSION <= 6
@@ -255,27 +282,46 @@
 #endif
                                       const SourceMetadata& sourceMetadata,
                                       openOutputStream_cb _hidl_cb) {
-#if MAJOR_VERSION <= 6
-    if (status_t status = CoreUtils::sourceMetadataToHal(sourceMetadata, nullptr);
-        status != NO_ERROR) {
-#else
-    if (status_t status = CoreUtils::sourceMetadataToHalV7(sourceMetadata,
-                                                           false /*ignoreNonVendorTags*/, nullptr);
-        status != NO_ERROR) {
-#endif
-        _hidl_cb(analyzeStatus("sourceMetadataToHal", status), nullptr, AudioConfig{});
-        return Void();
-    }
-    AudioConfig suggestedConfig;
-    auto [result, streamOut] =
-        openOutputStreamImpl(ioHandle, device, config, flags, &suggestedConfig);
-    if (streamOut) {
-        streamOut->updateSourceMetadata(sourceMetadata);
-    }
+    auto [result, streamOut, suggestedConfig] =
+            openOutputStreamImpl(ioHandle, device, config, sourceMetadata, flags);
     _hidl_cb(result, streamOut, suggestedConfig);
     return Void();
 }
 
+std::tuple<Result, sp<IStreamIn>, AudioConfig> Device::openInputStreamImpl(
+        int32_t ioHandle, const DeviceAddress& device, const AudioConfig& config,
+#if MAJOR_VERSION <= 6
+        AudioInputFlags flags,
+#else
+        const AudioInputFlags& flags,
+#endif
+        const SinkMetadata& sinkMetadata) {
+    if (sinkMetadata.tracks.size() == 0) {
+        // This should never happen, the framework must not create as stream
+        // if there is no client
+        ALOGE("openInputStream called without tracks connected");
+        return {Result::INVALID_ARGUMENTS, nullptr, AudioConfig{}};
+    }
+#if MAJOR_VERSION <= 6
+    if (status_t status = CoreUtils::sinkMetadataToHal(sinkMetadata, nullptr); status != NO_ERROR) {
+#else
+    if (status_t status = CoreUtils::sinkMetadataToHalV7(sinkMetadata,
+                                                         false /*ignoreNonVendorTags*/, nullptr);
+        status != NO_ERROR) {
+#endif
+        return {analyzeStatus("sinkMetadataToHal", status), nullptr, AudioConfig{}};
+    }
+    // Pick the first one as the main.
+    AudioSource source = sinkMetadata.tracks[0].source;
+    AudioConfig suggestedConfig;
+    auto [result, streamIn] =
+            openInputStreamCore(ioHandle, device, config, flags, source, &suggestedConfig);
+    if (streamIn) {
+        streamIn->updateSinkMetadata(sinkMetadata);
+    }
+    return {result, streamIn, suggestedConfig};
+}
+
 Return<void> Device::openInputStream(int32_t ioHandle, const DeviceAddress& device,
                                      const AudioConfig& config,
 #if MAJOR_VERSION <= 6
@@ -285,36 +331,25 @@
 #endif
                                      const SinkMetadata& sinkMetadata,
                                      openInputStream_cb _hidl_cb) {
-    if (sinkMetadata.tracks.size() == 0) {
-        // This should never happen, the framework must not create as stream
-        // if there is no client
-        ALOGE("openInputStream called without tracks connected");
-        _hidl_cb(Result::INVALID_ARGUMENTS, nullptr, AudioConfig{});
-        return Void();
-    }
-#if MAJOR_VERSION <= 6
-    if (status_t status = CoreUtils::sinkMetadataToHal(sinkMetadata, nullptr); status != NO_ERROR) {
-#else
-    if (status_t status = CoreUtils::sinkMetadataToHalV7(sinkMetadata,
-                                                         false /*ignoreNonVendorTags*/, nullptr);
-        status != NO_ERROR) {
-#endif
-        _hidl_cb(analyzeStatus("sinkMetadataToHal", status), nullptr, AudioConfig{});
-        return Void();
-    }
-    // Pick the first one as the main.
-    AudioSource source = sinkMetadata.tracks[0].source;
-    AudioConfig suggestedConfig;
-    auto [result, streamIn] =
-        openInputStreamImpl(ioHandle, device, config, flags, source, &suggestedConfig);
-    if (streamIn) {
-        streamIn->updateSinkMetadata(sinkMetadata);
-    }
+    auto [result, streamIn, suggestedConfig] =
+            openInputStreamImpl(ioHandle, device, config, flags, sinkMetadata);
     _hidl_cb(result, streamIn, suggestedConfig);
     return Void();
 }
 #endif /* MAJOR_VERSION */
 
+#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
+Return<void> Device::openOutputStream_7_1(int32_t ioHandle, const DeviceAddress& device,
+                                          const AudioConfig& config, const AudioOutputFlags& flags,
+                                          const SourceMetadata& sourceMetadata,
+                                          openOutputStream_7_1_cb _hidl_cb) {
+    auto [result, streamOut, suggestedConfig] =
+            openOutputStreamImpl(ioHandle, device, config, sourceMetadata, flags);
+    _hidl_cb(result, streamOut, suggestedConfig);
+    return Void();
+}
+#endif  // V7.1
+
 Return<bool> Device::supportsAudioPatches() {
     return version() >= AUDIO_DEVICE_API_VERSION_3_0;
 }
@@ -571,6 +606,21 @@
 
 #endif
 
+#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
+Return<Result> Device::setConnectedState_7_1(const AudioPort& devicePort, bool connected) {
+    if (version() >= AUDIO_DEVICE_API_VERSION_3_2 &&
+        mDevice->set_device_connected_state_v7 != nullptr) {
+        audio_port_v7 halPort;
+        if (status_t status = HidlUtils::audioPortToHal(devicePort, &halPort); status != NO_ERROR) {
+            return analyzeStatus("audioPortToHal", status);
+        }
+        return analyzeStatus("set_device_connected_state_v7",
+                             mDevice->set_device_connected_state_v7(mDevice, &halPort, connected));
+    }
+    return Result::NOT_SUPPORTED;
+}
+#endif
+
 }  // namespace implementation
 }  // namespace CPP_VERSION
 }  // namespace audio
diff --git a/audio/core/all-versions/default/DevicesFactory.cpp b/audio/core/all-versions/default/DevicesFactory.cpp
index 729f18c..f44daf0 100644
--- a/audio/core/all-versions/default/DevicesFactory.cpp
+++ b/audio/core/all-versions/default/DevicesFactory.cpp
@@ -47,22 +47,54 @@
     _hidl_cb(Result::INVALID_ARGUMENTS, nullptr);
     return Void();
 }
+
+Return<void> DevicesFactory::openDevice(const char* moduleName, openDevice_cb _hidl_cb) {
+    return openDevice<implementation::Device>(moduleName, _hidl_cb);
+}
 #elif MAJOR_VERSION >= 4
 Return<void> DevicesFactory::openDevice(const hidl_string& moduleName, openDevice_cb _hidl_cb) {
     if (moduleName == AUDIO_HARDWARE_MODULE_ID_PRIMARY) {
         return openDevice<PrimaryDevice>(moduleName.c_str(), _hidl_cb);
     }
-    return openDevice(moduleName.c_str(), _hidl_cb);
+    return openDevice<implementation::Device>(moduleName.c_str(), _hidl_cb);
 }
 Return<void> DevicesFactory::openPrimaryDevice(openPrimaryDevice_cb _hidl_cb) {
     return openDevice<PrimaryDevice>(AUDIO_HARDWARE_MODULE_ID_PRIMARY, _hidl_cb);
 }
 #endif
 
-Return<void> DevicesFactory::openDevice(const char* moduleName, openDevice_cb _hidl_cb) {
-    return openDevice<implementation::Device>(moduleName, _hidl_cb);
+#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
+Return<void> DevicesFactory::openDevice_7_1(const hidl_string& moduleName,
+                                            openDevice_7_1_cb _hidl_cb) {
+    if (moduleName == AUDIO_HARDWARE_MODULE_ID_PRIMARY) {
+        Result result;
+        sp<IPrimaryDevice> primary;
+        auto ret = openDevice<PrimaryDevice>(
+                AUDIO_HARDWARE_MODULE_ID_PRIMARY,
+                [&result, &primary](Result r, const sp<IPrimaryDevice>& p) {
+                    result = r;
+                    primary = p;
+                });
+        if (ret.isOk() && result == Result::OK && primary != nullptr) {
+            auto getDeviceRet = primary->getDevice();
+            if (getDeviceRet.isOk()) {
+                _hidl_cb(result, getDeviceRet);
+            } else {
+                _hidl_cb(Result::NOT_INITIALIZED, nullptr);
+            }
+        } else {
+            _hidl_cb(result, nullptr);
+        }
+        return Void();
+    }
+    return openDevice<implementation::Device>(moduleName.c_str(), _hidl_cb);
 }
 
+Return<void> DevicesFactory::openPrimaryDevice_7_1(openPrimaryDevice_7_1_cb _hidl_cb) {
+    return openDevice<PrimaryDevice>(AUDIO_HARDWARE_MODULE_ID_PRIMARY, _hidl_cb);
+}
+#endif  // V7.1
+
 template <class DeviceShim, class Callback>
 Return<void> DevicesFactory::openDevice(const char* moduleName, Callback _hidl_cb) {
     audio_hw_device_t* halDevice;
diff --git a/audio/core/all-versions/default/ParametersUtil.cpp b/audio/core/all-versions/default/ParametersUtil.cpp
index 4d53645..e21eff2 100644
--- a/audio/core/all-versions/default/ParametersUtil.cpp
+++ b/audio/core/all-versions/default/ParametersUtil.cpp
@@ -24,7 +24,7 @@
 namespace android {
 namespace hardware {
 namespace audio {
-namespace CPP_VERSION {
+namespace CORE_TYPES_CPP_VERSION {
 namespace implementation {
 
 /** Converts a status_t in Result according to the rules of AudioParameter::get*
@@ -168,7 +168,7 @@
 }
 
 }  // namespace implementation
-}  // namespace CPP_VERSION
+}  // namespace CORE_TYPES_CPP_VERSION
 }  // namespace audio
 }  // namespace hardware
 }  // namespace android
diff --git a/audio/core/all-versions/default/PrimaryDevice.cpp b/audio/core/all-versions/default/PrimaryDevice.cpp
index fe56177..cf162f1 100644
--- a/audio/core/all-versions/default/PrimaryDevice.cpp
+++ b/audio/core/all-versions/default/PrimaryDevice.cpp
@@ -29,6 +29,10 @@
 namespace CPP_VERSION {
 namespace implementation {
 
+namespace util {
+using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION::implementation::util;
+}
+
 PrimaryDevice::PrimaryDevice(audio_hw_device_t* device) : mDevice(new Device(device)) {}
 
 PrimaryDevice::~PrimaryDevice() {
@@ -195,7 +199,7 @@
 
 // Methods from ::android::hardware::audio::CPP_VERSION::IPrimaryDevice follow.
 Return<Result> PrimaryDevice::setVoiceVolume(float volume) {
-    if (!isGainNormalized(volume)) {
+    if (!util::isGainNormalized(volume)) {
         ALOGW("Can not set a voice volume (%f) outside [0,1]", volume);
         return Result::INVALID_ARGUMENTS;
     }
@@ -326,7 +330,7 @@
     return mDevice->setParam(AUDIO_PARAMETER_KEY_HFP_SET_SAMPLING_RATE, int(sampleRateHz));
 }
 Return<Result> PrimaryDevice::setBtHfpVolume(float volume) {
-    if (!isGainNormalized(volume)) {
+    if (!util::isGainNormalized(volume)) {
         ALOGW("Can not set BT HFP volume (%f) outside [0,1]", volume);
         return Result::INVALID_ARGUMENTS;
     }
diff --git a/audio/core/all-versions/default/Stream.cpp b/audio/core/all-versions/default/Stream.cpp
index 7e32573..8e85a8b 100644
--- a/audio/core/all-versions/default/Stream.cpp
+++ b/audio/core/all-versions/default/Stream.cpp
@@ -37,8 +37,12 @@
 namespace CPP_VERSION {
 namespace implementation {
 
-using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::HidlUtils;
 using ::android::hardware::audio::common::utils::splitString;
+using ::android::hardware::audio::CORE_TYPES_CPP_VERSION::implementation::CoreUtils;
+namespace util {
+using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION::implementation::util;
+}
 
 Stream::Stream(bool isInput, audio_stream_t* stream) : mIsInput(isInput), mStream(stream) {
     (void)mIsInput;  // prevent 'unused field' warnings in pre-V7 versions.
diff --git a/audio/core/all-versions/default/StreamIn.cpp b/audio/core/all-versions/default/StreamIn.cpp
index 2aeee43..2bea425 100644
--- a/audio/core/all-versions/default/StreamIn.cpp
+++ b/audio/core/all-versions/default/StreamIn.cpp
@@ -37,7 +37,11 @@
 namespace CPP_VERSION {
 namespace implementation {
 
-using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::HidlUtils;
+using ::android::hardware::audio::CORE_TYPES_CPP_VERSION::implementation::CoreUtils;
+namespace util {
+using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION::implementation::util;
+}
 
 namespace {
 
@@ -348,7 +352,7 @@
 }
 
 Return<Result> StreamIn::setGain(float gain) {
-    if (!isGainNormalized(gain)) {
+    if (!util::isGainNormalized(gain)) {
         ALOGW("Can not set a stream input gain (%f) outside [0,1]", gain);
         return Result::INVALID_ARGUMENTS;
     }
diff --git a/audio/core/all-versions/default/StreamOut.cpp b/audio/core/all-versions/default/StreamOut.cpp
index d027231..09df4ed 100644
--- a/audio/core/all-versions/default/StreamOut.cpp
+++ b/audio/core/all-versions/default/StreamOut.cpp
@@ -39,7 +39,11 @@
 namespace CPP_VERSION {
 namespace implementation {
 
-using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::HidlUtils;
+using ::android::hardware::audio::CORE_TYPES_CPP_VERSION::implementation::CoreUtils;
+namespace util {
+using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION::implementation::util;
+}
 
 namespace {
 
@@ -334,7 +338,7 @@
     if (mStream->set_volume == NULL) {
         return Result::NOT_SUPPORTED;
     }
-    if (!isGainNormalized(left)) {
+    if (!util::isGainNormalized(left)) {
         ALOGW("Can not set a stream output volume {%f, %f} outside [0,1]", left, right);
         return Result::INVALID_ARGUMENTS;
     }
@@ -757,6 +761,73 @@
     ALOGW_IF(!result.isOk(), "Client callback failed: %s", result.description().c_str());
     return 0;
 }
+
+#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
+Return<Result> StreamOut::setLatencyMode(LatencyMode mode) {
+    return mStream->set_latency_mode != nullptr
+                   ? Stream::analyzeStatus(
+                             "set_latency_mode",
+                             mStream->set_latency_mode(mStream,
+                                                       static_cast<audio_latency_mode_t>(mode)))
+                   : Result::NOT_SUPPORTED;
+};
+
+Return<void> StreamOut::getRecommendedLatencyModes(getRecommendedLatencyModes_cb _hidl_cb) {
+    Result retval = Result::NOT_SUPPORTED;
+    hidl_vec<LatencyMode> hidlModes;
+    size_t num_modes = AUDIO_LATENCY_MODE_CNT;
+    audio_latency_mode_t modes[AUDIO_LATENCY_MODE_CNT];
+
+    if (mStream->get_recommended_latency_modes != nullptr &&
+        mStream->get_recommended_latency_modes(mStream, &modes[0], &num_modes) == 0) {
+        if (num_modes == 0 || num_modes > AUDIO_LATENCY_MODE_CNT) {
+            ALOGW("%s invalid number of modes returned: %zu", __func__, num_modes);
+            retval = Result::INVALID_STATE;
+        } else {
+            hidlModes.resize(num_modes);
+            for (size_t i = 0; i < num_modes; ++i) {
+                hidlModes[i] = static_cast<LatencyMode>(modes[i]);
+            }
+            retval = Result::OK;
+        }
+    }
+    _hidl_cb(retval, hidlModes);
+    return Void();
+};
+
+// static
+void StreamOut::latencyModeCallback(audio_latency_mode_t* modes, size_t num_modes, void* cookie) {
+    StreamOut* self = reinterpret_cast<StreamOut*>(cookie);
+    sp<IStreamOutLatencyModeCallback> callback = self->mLatencyModeCallback.load();
+    if (callback.get() == nullptr) return;
+
+    ALOGV("%s", __func__);
+
+    if (num_modes == 0 || num_modes > AUDIO_LATENCY_MODE_CNT) {
+        ALOGW("%s invalid number of modes returned: %zu", __func__, num_modes);
+        return;
+    }
+
+    hidl_vec<LatencyMode> hidlModes(num_modes);
+    for (size_t i = 0; i < num_modes; ++i) {
+        hidlModes[i] = static_cast<LatencyMode>(modes[i]);
+    }
+    Return<void> result = callback->onRecommendedLatencyModeChanged(hidlModes);
+    ALOGW_IF(!result.isOk(), "Client callback failed: %s", result.description().c_str());
+}
+
+Return<Result> StreamOut::setLatencyModeCallback(
+        const sp<IStreamOutLatencyModeCallback>& callback) {
+    if (mStream->set_latency_mode_callback == nullptr) return Result::NOT_SUPPORTED;
+    int result = mStream->set_latency_mode_callback(mStream, StreamOut::latencyModeCallback, this);
+    if (result == 0) {
+        mLatencyModeCallback = callback;
+    }
+    return Stream::analyzeStatus("set_latency_mode_callback", result, {ENOSYS} /*ignore*/);
+};
+
+#endif
+
 #endif
 
 }  // namespace implementation
diff --git a/audio/core/all-versions/default/TEST_MAPPING b/audio/core/all-versions/default/TEST_MAPPING
index 1e29440..07e98f3 100644
--- a/audio/core/all-versions/default/TEST_MAPPING
+++ b/audio/core/all-versions/default/TEST_MAPPING
@@ -4,6 +4,9 @@
       "name": "android.hardware.audio@7.0-util_tests"
     },
     {
+      "name": "android.hardware.audio@7.1-util_tests"
+    },
+    {
       "name": "HalAudioV6_0GeneratorTest"
     },
     {
diff --git a/audio/core/all-versions/default/include/core/default/Device.h b/audio/core/all-versions/default/include/core/default/Device.h
index 94cad53..0696f97 100644
--- a/audio/core/all-versions/default/include/core/default/Device.h
+++ b/audio/core/all-versions/default/include/core/default/Device.h
@@ -44,7 +44,10 @@
 using ::android::hardware::hidl_vec;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using ::android::hardware::audio::CORE_TYPES_CPP_VERSION::implementation::CoreUtils;
+using ::android::hardware::audio::CORE_TYPES_CPP_VERSION::implementation::ParametersUtil;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
+using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION;
 using namespace ::android::hardware::audio::CPP_VERSION;
 using AudioInputFlags = CoreUtils::AudioInputFlags;
 using AudioOutputFlags = CoreUtils::AudioOutputFlags;
@@ -63,14 +66,32 @@
     Return<void> getInputBufferSize(const AudioConfig& config,
                                     getInputBufferSize_cb _hidl_cb) override;
 
-    std::tuple<Result, sp<IStreamOut>> openOutputStreamImpl(int32_t ioHandle,
+    std::tuple<Result, sp<IStreamOut>> openOutputStreamCore(int32_t ioHandle,
                                                             const DeviceAddress& device,
                                                             const AudioConfig& config,
                                                             const AudioOutputFlags& flags,
                                                             AudioConfig* suggestedConfig);
-    std::tuple<Result, sp<IStreamIn>> openInputStreamImpl(
+    std::tuple<Result, sp<IStreamIn>> openInputStreamCore(
             int32_t ioHandle, const DeviceAddress& device, const AudioConfig& config,
             const AudioInputFlags& flags, AudioSource source, AudioConfig* suggestedConfig);
+#if MAJOR_VERSION >= 4
+    std::tuple<Result, sp<IStreamOut>, AudioConfig> openOutputStreamImpl(
+            int32_t ioHandle, const DeviceAddress& device, const AudioConfig& config,
+            const SourceMetadata& sourceMetadata,
+#if MAJOR_VERSION <= 6
+            AudioOutputFlags flags);
+#else
+            const AudioOutputFlags& flags);
+#endif
+    std::tuple<Result, sp<IStreamIn>, AudioConfig> openInputStreamImpl(
+            int32_t ioHandle, const DeviceAddress& device, const AudioConfig& config,
+#if MAJOR_VERSION <= 6
+            AudioInputFlags flags,
+#else
+            const AudioInputFlags& flags,
+#endif
+            const SinkMetadata& sinkMetadata);
+#endif  // MAJOR_VERSION >= 4
 
     Return<void> openOutputStream(int32_t ioHandle, const DeviceAddress& device,
                                   const AudioConfig& config,
@@ -97,6 +118,13 @@
 #endif
                                  openInputStream_cb _hidl_cb) override;
 
+#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
+    Return<void> openOutputStream_7_1(int32_t ioHandle, const DeviceAddress& device,
+                                      const AudioConfig& config, const AudioOutputFlags& flags,
+                                      const SourceMetadata& sourceMetadata,
+                                      openOutputStream_7_1_cb _hidl_cb) override;
+#endif
+
     Return<bool> supportsAudioPatches() override;
     Return<void> createAudioPatch(const hidl_vec<AudioPortConfig>& sources,
                                   const hidl_vec<AudioPortConfig>& sinks,
@@ -131,6 +159,9 @@
                                   const hidl_vec<AudioPortConfig>& sinks,
                                   createAudioPatch_cb _hidl_cb) override;
 #endif
+#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
+    Return<Result> setConnectedState_7_1(const AudioPort& devicePort, bool connected) override;
+#endif
     Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
 
     // Utility methods for extending interfaces.
diff --git a/audio/core/all-versions/default/include/core/default/DevicesFactory.h b/audio/core/all-versions/default/include/core/default/DevicesFactory.h
index 9f93a38..566bc8a 100644
--- a/audio/core/all-versions/default/include/core/default/DevicesFactory.h
+++ b/audio/core/all-versions/default/include/core/default/DevicesFactory.h
@@ -44,11 +44,17 @@
     Return<void> openDevice(const hidl_string& device, openDevice_cb _hidl_cb) override;
     Return<void> openPrimaryDevice(openPrimaryDevice_cb _hidl_cb) override;
 #endif
+#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
+    Return<void> openDevice_7_1(const hidl_string& device, openDevice_7_1_cb _hidl_cb) override;
+    Return<void> openPrimaryDevice_7_1(openPrimaryDevice_7_1_cb _hidl_cb) override;
+#endif
 
-   private:
+  private:
     template <class DeviceShim, class Callback>
     Return<void> openDevice(const char* moduleName, Callback _hidl_cb);
+#if MAJOR_VERSION == 2
     Return<void> openDevice(const char* moduleName, openDevice_cb _hidl_cb);
+#endif
 
     static int loadAudioInterface(const char* if_name, audio_hw_device_t** dev);
 };
diff --git a/audio/core/all-versions/default/include/core/default/ParametersUtil.h b/audio/core/all-versions/default/include/core/default/ParametersUtil.h
index 45d9b21..25c193a 100644
--- a/audio/core/all-versions/default/include/core/default/ParametersUtil.h
+++ b/audio/core/all-versions/default/include/core/default/ParametersUtil.h
@@ -17,7 +17,10 @@
 #ifndef ANDROID_HARDWARE_AUDIO_PARAMETERS_UTIL_H_
 #define ANDROID_HARDWARE_AUDIO_PARAMETERS_UTIL_H_
 
-#include PATH(android/hardware/audio/FILE_VERSION/types.h)
+// clang-format off
+#include PATH(android/hardware/audio/common/COMMON_TYPES_FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/types.h)
+// clang-format on
 
 #include <functional>
 #include <memory>
@@ -28,13 +31,13 @@
 namespace android {
 namespace hardware {
 namespace audio {
-namespace CPP_VERSION {
+namespace CORE_TYPES_CPP_VERSION {
 namespace implementation {
 
 using ::android::hardware::hidl_string;
 using ::android::hardware::hidl_vec;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
-using namespace ::android::hardware::audio::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
+using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION;
 
 class ParametersUtil {
    public:
@@ -62,7 +65,7 @@
 };
 
 }  // namespace implementation
-}  // namespace CPP_VERSION
+}  // namespace CORE_TYPES_CPP_VERSION
 }  // namespace audio
 }  // namespace hardware
 }  // namespace android
diff --git a/audio/core/all-versions/default/include/core/default/PrimaryDevice.h b/audio/core/all-versions/default/include/core/default/PrimaryDevice.h
index 5f65acf..8b37e01 100644
--- a/audio/core/all-versions/default/include/core/default/PrimaryDevice.h
+++ b/audio/core/all-versions/default/include/core/default/PrimaryDevice.h
@@ -36,7 +36,8 @@
 using ::android::hardware::hidl_vec;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
+using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION;
 using namespace ::android::hardware::audio::CPP_VERSION;
 
 struct PrimaryDevice : public IPrimaryDevice {
@@ -135,8 +136,10 @@
     Return<Result> setBtHfpVolume(float volume) override;
     Return<Result> updateRotation(IPrimaryDevice::Rotation rotation) override;
 #endif
-
-   private:
+#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
+    Return<sp<::android::hardware::audio::V7_1::IDevice>> getDevice() override { return mDevice; }
+#endif
+  private:
     sp<Device> mDevice;
 
     virtual ~PrimaryDevice();
diff --git a/audio/core/all-versions/default/include/core/default/Stream.h b/audio/core/all-versions/default/include/core/default/Stream.h
index 66d60e3..4e79884 100644
--- a/audio/core/all-versions/default/include/core/default/Stream.h
+++ b/audio/core/all-versions/default/include/core/default/Stream.h
@@ -17,7 +17,9 @@
 #ifndef ANDROID_HARDWARE_AUDIO_STREAM_H
 #define ANDROID_HARDWARE_AUDIO_STREAM_H
 
-#include PATH(android/hardware/audio/FILE_VERSION/IStream.h)
+// clang-format off
+#include PATH(android/hardware/audio/COMMON_TYPES_FILE_VERSION/IStream.h)
+// clang-format on
 
 #include "ParametersUtil.h"
 
@@ -41,10 +43,13 @@
 using ::android::hardware::hidl_vec;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
+using ::android::hardware::audio::CORE_TYPES_CPP_VERSION::implementation::ParametersUtil;
 #if MAJOR_VERSION <= 6
-using ::android::hardware::audio::common::CPP_VERSION::implementation::AudioChannelBitfield;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::
+        AudioChannelBitfield;
 #endif
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
+using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION;
 using namespace ::android::hardware::audio::CPP_VERSION;
 
 struct Stream : public IStream, public ParametersUtil {
diff --git a/audio/core/all-versions/default/include/core/default/StreamIn.h b/audio/core/all-versions/default/include/core/default/StreamIn.h
index a980f3f..4627eec 100644
--- a/audio/core/all-versions/default/include/core/default/StreamIn.h
+++ b/audio/core/all-versions/default/include/core/default/StreamIn.h
@@ -17,7 +17,9 @@
 #ifndef ANDROID_HARDWARE_AUDIO_STREAMIN_H
 #define ANDROID_HARDWARE_AUDIO_STREAMIN_H
 
-#include PATH(android/hardware/audio/FILE_VERSION/IStreamIn.h)
+// clang-format off
+#include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/IStreamIn.h)
+// clang-format on
 
 #include "Device.h"
 #include "Stream.h"
@@ -42,7 +44,8 @@
 using ::android::hardware::hidl_vec;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
+using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION;
 using namespace ::android::hardware::audio::CPP_VERSION;
 
 struct StreamIn : public IStreamIn {
diff --git a/audio/core/all-versions/default/include/core/default/StreamOut.h b/audio/core/all-versions/default/include/core/default/StreamOut.h
index 0b07972..ce5253f 100644
--- a/audio/core/all-versions/default/include/core/default/StreamOut.h
+++ b/audio/core/all-versions/default/include/core/default/StreamOut.h
@@ -43,7 +43,8 @@
 using ::android::hardware::hidl_vec;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
+using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION;
 using namespace ::android::hardware::audio::CPP_VERSION;
 
 struct StreamOut : public IStreamOut {
@@ -152,6 +153,12 @@
     Result doUpdateSourceMetadata(const SourceMetadata& sourceMetadata);
 #if MAJOR_VERSION >= 7
     Result doUpdateSourceMetadataV7(const SourceMetadata& sourceMetadata);
+#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
+    Return<Result> setLatencyMode(LatencyMode mode) override;
+    Return<void> getRecommendedLatencyModes(getRecommendedLatencyModes_cb _hidl_cb) override;
+    Return<Result> setLatencyModeCallback(
+            const sp<IStreamOutLatencyModeCallback>& callback) override;
+#endif
 #endif
 #endif  // MAJOR_VERSION >= 4
 
@@ -162,6 +169,9 @@
     mediautils::atomic_sp<IStreamOutCallback> mCallback;  // for non-blocking write and drain
 #if MAJOR_VERSION >= 6
     mediautils::atomic_sp<IStreamOutEventCallback> mEventCallback;
+#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
+    mediautils::atomic_sp<IStreamOutLatencyModeCallback> mLatencyModeCallback;
+#endif
 #endif
     std::unique_ptr<CommandMQ> mCommandMQ;
     std::unique_ptr<DataMQ> mDataMQ;
@@ -176,6 +186,9 @@
 
 #if MAJOR_VERSION >= 6
     static int asyncEventCallback(stream_event_callback_type_t event, void* param, void* cookie);
+#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
+    static void latencyModeCallback(audio_latency_mode_t* modes, size_t num_modes, void* cookie);
+#endif
 #endif
 };
 
diff --git a/audio/core/all-versions/default/include/core/default/Util.h b/audio/core/all-versions/default/include/core/default/Util.h
index 78ae03e..abf5317 100644
--- a/audio/core/all-versions/default/include/core/default/Util.h
+++ b/audio/core/all-versions/default/include/core/default/Util.h
@@ -17,7 +17,9 @@
 #ifndef ANDROID_HARDWARE_AUDIO_UTIL_H
 #define ANDROID_HARDWARE_AUDIO_UTIL_H
 
-#include PATH(android/hardware/audio/FILE_VERSION/types.h)
+// clang-format off
+#include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/types.h)
+// clang-format on
 
 #include <algorithm>
 #include <vector>
@@ -27,19 +29,19 @@
 namespace android {
 namespace hardware {
 namespace audio {
-namespace CPP_VERSION {
+namespace CORE_TYPES_CPP_VERSION {
 namespace implementation {
 
-using namespace ::android::hardware::audio::common::CPP_VERSION;
-using namespace ::android::hardware::audio::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
+using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION;
+
+namespace util {
 
 /** @return true if gain is between 0 and 1 included. */
 constexpr bool isGainNormalized(float gain) {
     return gain >= 0.0 && gain <= 1.0;
 }
 
-namespace util {
-
 template <typename T>
 inline bool element_in(T e, const std::vector<T>& v) {
     return std::find(v.begin(), v.end(), e) != v.end();
@@ -72,7 +74,7 @@
 
 }  // namespace util
 }  // namespace implementation
-}  // namespace CPP_VERSION
+}  // namespace CORE_TYPES_CPP_VERSION
 }  // namespace audio
 }  // namespace hardware
 }  // namespace android
diff --git a/audio/core/all-versions/default/util/Android.bp b/audio/core/all-versions/default/util/Android.bp
index 7caf18d..b96f2d2 100644
--- a/audio/core/all-versions/default/util/Android.bp
+++ b/audio/core/all-versions/default/util/Android.bp
@@ -112,6 +112,25 @@
     ],
 }
 
+cc_library {
+    name: "android.hardware.audio@7.1-util",
+    defaults: ["android.hardware.audio-util_default"],
+    shared_libs: [
+        "android.hardware.audio.common@7.0",
+        "android.hardware.audio.common@7.1-enums",
+        "android.hardware.audio.common@7.1-util",
+        "android.hardware.audio@7.1",
+        "libbase",
+    ],
+    cflags: [
+        "-DMAJOR_VERSION=7",
+        "-DMINOR_VERSION=1",
+        "-DCOMMON_TYPES_MINOR_VERSION=0",
+        "-DCORE_TYPES_MINOR_VERSION=0",
+        "-include common/all-versions/VersionMacro.h",
+    ],
+}
+
 // Note: this isn't a VTS test, but rather a unit test
 // to verify correctness of conversion utilities.
 cc_test {
@@ -145,3 +164,37 @@
 
     test_suites: ["device-tests"],
 }
+
+cc_test {
+    name: "android.hardware.audio@7.1-util_tests",
+    defaults: ["android.hardware.audio-util_default"],
+
+    srcs: ["tests/coreutils_tests.cpp"],
+
+    // Use static linking to allow running in presubmit on
+    // targets that don't have HAL V7.1.
+    static_libs: [
+        "android.hardware.audio.common@7.0",
+        "android.hardware.audio.common@7.1-enums",
+        "android.hardware.audio.common@7.1-util",
+        "android.hardware.audio@7.1",
+        "android.hardware.audio@7.1-util",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "libxml2",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+        "-DMAJOR_VERSION=7",
+        "-DMINOR_VERSION=1",
+        "-DCOMMON_TYPES_MINOR_VERSION=0",
+        "-DCORE_TYPES_MINOR_VERSION=0",
+        "-include common/all-versions/VersionMacro.h",
+    ],
+
+    test_suites: ["device-tests"],
+}
diff --git a/audio/core/all-versions/default/util/CoreUtils.cpp b/audio/core/all-versions/default/util/CoreUtils.cpp
index 773be21..8e83ea1 100644
--- a/audio/core/all-versions/default/util/CoreUtils.cpp
+++ b/audio/core/all-versions/default/util/CoreUtils.cpp
@@ -15,24 +15,24 @@
  */
 
 #if MAJOR_VERSION >= 7
-#include <android_audio_policy_configuration_V7_0-enums.h>
+#include PATH(APM_XSD_ENUMS_H_FILENAME)
 #endif
 #include <HidlUtils.h>
 #include <log/log.h>
 
 #include "util/CoreUtils.h"
 
-using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::HidlUtils;
 #if MAJOR_VERSION >= 7
 namespace xsd {
-using namespace ::android::audio::policy::configuration::V7_0;
+using namespace ::android::audio::policy::configuration::CPP_VERSION;
 }
 #endif
 
 namespace android {
 namespace hardware {
 namespace audio {
-namespace CPP_VERSION {
+namespace CORE_TYPES_CPP_VERSION {
 namespace implementation {
 
 #define CONVERT_CHECKED(expr, result)                   \
@@ -389,7 +389,7 @@
 
 #if MAJOR_VERSION >= 7
 namespace xsd {
-using namespace ::android::audio::policy::configuration::V7_0;
+using namespace ::android::audio::policy::configuration::CPP_VERSION;
 }
 
 status_t CoreUtils::audioInputFlagsFromHal(audio_input_flags_t halFlagMask,
@@ -470,7 +470,7 @@
 #endif
 
 }  // namespace implementation
-}  // namespace CPP_VERSION
+}  // namespace CORE_TYPES_CPP_VERSION
 }  // namespace audio
 }  // namespace hardware
 }  // namespace android
diff --git a/audio/core/all-versions/default/util/include/util/CoreUtils.h b/audio/core/all-versions/default/util/include/util/CoreUtils.h
index 1e5272a..dc35772 100644
--- a/audio/core/all-versions/default/util/include/util/CoreUtils.h
+++ b/audio/core/all-versions/default/util/include/util/CoreUtils.h
@@ -17,7 +17,7 @@
 #pragma once
 
 // clang-format off
-#include PATH(android/hardware/audio/FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/types.h)
 // clang-format off
 
 #include <vector>
@@ -30,13 +30,13 @@
 namespace android {
 namespace hardware {
 namespace audio {
-namespace CPP_VERSION {
+namespace CORE_TYPES_CPP_VERSION {
 namespace implementation {
 
 using ::android::hardware::audio::common::utils::EnumBitfield;
 using ::android::hardware::hidl_vec;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
-using namespace ::android::hardware::audio::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
+using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION;
 
 struct CoreUtils {
     // Note: the converters for DeviceAddress have to be in CoreUtils for HAL V4
@@ -93,8 +93,8 @@
         return NO_ERROR;
     }
 #else
-    using AudioInputFlags = hidl_vec<::android::hardware::audio::CPP_VERSION::AudioInOutFlag>;
-    using AudioOutputFlags = hidl_vec<::android::hardware::audio::CPP_VERSION::AudioInOutFlag>;
+    using AudioInputFlags = hidl_vec<::android::hardware::audio::CORE_TYPES_CPP_VERSION::AudioInOutFlag>;
+    using AudioOutputFlags = hidl_vec<::android::hardware::audio::CORE_TYPES_CPP_VERSION::AudioInOutFlag>;
     static status_t audioInputFlagsFromHal(audio_input_flags_t halFlagMask, AudioInputFlags* flags);
     static status_t audioInputFlagsToHal(const AudioInputFlags& flags, audio_input_flags_t* halFlagMask);
     static status_t audioOutputFlagsFromHal(audio_output_flags_t halFlagMask, AudioOutputFlags* flags);
diff --git a/audio/core/all-versions/default/util/tests/coreutils_tests.cpp b/audio/core/all-versions/default/util/tests/coreutils_tests.cpp
index 0c18482..0e15960 100644
--- a/audio/core/all-versions/default/util/tests/coreutils_tests.cpp
+++ b/audio/core/all-versions/default/util/tests/coreutils_tests.cpp
@@ -22,18 +22,18 @@
 #define LOG_TAG "CoreUtils_Test"
 #include <log/log.h>
 
-#include <android_audio_policy_configuration_V7_0-enums.h>
+#include PATH(APM_XSD_ENUMS_H_FILENAME)
 #include <system/audio.h>
 #include <util/CoreUtils.h>
 #include <xsdc/XsdcSupport.h>
 
 using namespace android;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
-using namespace ::android::hardware::audio::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
+using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION;
 using ::android::hardware::hidl_vec;
-using ::android::hardware::audio::CPP_VERSION::implementation::CoreUtils;
+using ::android::hardware::audio::CORE_TYPES_CPP_VERSION::implementation::CoreUtils;
 namespace xsd {
-using namespace ::android::audio::policy::configuration::V7_0;
+using namespace ::android::audio::policy::configuration::CPP_VERSION;
 }
 
 static constexpr audio_channel_mask_t kInvalidHalChannelMask = AUDIO_CHANNEL_INVALID;
diff --git a/audio/core/all-versions/vts/functional/2.0/AudioPrimaryHidlHalUtils.h b/audio/core/all-versions/vts/functional/2.0/AudioPrimaryHidlHalUtils.h
index 1cffd41..dd80dd6 100644
--- a/audio/core/all-versions/vts/functional/2.0/AudioPrimaryHidlHalUtils.h
+++ b/audio/core/all-versions/vts/functional/2.0/AudioPrimaryHidlHalUtils.h
@@ -14,16 +14,18 @@
  * limitations under the License.
  */
 
+// clang-format off
 #include PATH(android/hardware/audio/FILE_VERSION/IStream.h)
-#include PATH(android/hardware/audio/FILE_VERSION/types.h)
-#include PATH(android/hardware/audio/common/FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/common/COMMON_TYPES_FILE_VERSION/types.h)
+// clang-format on
 #include <hidl/HidlSupport.h>
 
 using ::android::hardware::hidl_handle;
 using ::android::hardware::hidl_string;
 using ::android::hardware::hidl_vec;
-using ::android::hardware::audio::common::CPP_VERSION::AudioChannelMask;
-using ::android::hardware::audio::common::CPP_VERSION::AudioFormat;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::AudioChannelMask;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::AudioFormat;
 using ::android::hardware::audio::CPP_VERSION::IStream;
 using ::android::hardware::audio::CPP_VERSION::ParameterValue;
 using ::android::hardware::audio::CPP_VERSION::Result;
diff --git a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
index 787654b..7f4a777 100644
--- a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
@@ -17,7 +17,7 @@
 #include "AudioPrimaryHidlHalTest.h"
 
 #if MAJOR_VERSION >= 7
-#include <android_audio_policy_configuration_V7_0.h>
+#include PATH(APM_XSD_H_FILENAME)
 #include <xsdc/XsdcSupport.h>
 
 using android::xsdc_enum_range;
@@ -28,17 +28,36 @@
     if (getDeviceName() != DeviceManager::kPrimaryDevice) {
         GTEST_SKIP() << "No primary device on this factory";  // returns
     }
+    EXPECT_TRUE(DeviceManager::getInstance().resetPrimary(getFactoryName()));
 
-    {  // Scope for device SPs
-        sp<IDevice> baseDevice =
-                DeviceManager::getInstance().get(getFactoryName(), DeviceManager::kPrimaryDevice);
-        ASSERT_TRUE(baseDevice != nullptr);
-        Return<sp<IPrimaryDevice>> primaryDevice = IPrimaryDevice::castFrom(baseDevice);
+    // Must use IDevicesFactory directly because DeviceManager always uses
+    // the latest interfaces version and corresponding methods for opening
+    // them. However, in minor package uprevs IPrimaryDevice does not inherit
+    // IDevice from the same package and thus IDevice can not be upcasted
+    // (see the interfaces in V7.1).
+    auto factory = DevicesFactoryManager::getInstance().get(getFactoryName());
+    ASSERT_TRUE(factory != nullptr);
+    sp<::android::hardware::audio::CORE_TYPES_CPP_VERSION::IDevice> baseDevice;
+    Result result;
+    auto ret = factory->openDevice(DeviceManager::kPrimaryDevice, returnIn(result, baseDevice));
+    ASSERT_TRUE(ret.isOk()) << ret.description();
+    ASSERT_EQ(Result::OK, result);
+    ASSERT_TRUE(baseDevice != nullptr);
+    {
+        Return<sp<::android::hardware::audio::CORE_TYPES_CPP_VERSION::IPrimaryDevice>>
+                primaryDevice = ::android::hardware::audio::CORE_TYPES_CPP_VERSION::IPrimaryDevice::
+                        castFrom(baseDevice);
         EXPECT_TRUE(primaryDevice.isOk());
-        EXPECT_TRUE(sp<IPrimaryDevice>(primaryDevice) != nullptr);
+        EXPECT_TRUE(sp<::android::hardware::audio::CORE_TYPES_CPP_VERSION::IPrimaryDevice>(
+                            primaryDevice) != nullptr);
     }
-    EXPECT_TRUE(
-            DeviceManager::getInstance().reset(getFactoryName(), DeviceManager::kPrimaryDevice));
+#if MAJOR_VERSION < 6
+    baseDevice.clear();
+    DeviceManager::waitForInstanceDestruction();
+#else
+    auto closeRet = baseDevice->close();
+    EXPECT_TRUE(closeRet.isOk());
+#endif
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -183,7 +202,7 @@
                areAudioPatchesSupported() ? doc::partialTest("Audio patches are supported")
                                           : testSetDevices(stream.get(), address))
 
-static void checkGetHwAVSync(IDevice* device) {
+static void checkGetHwAVSync(::android::hardware::audio::CPP_VERSION::IDevice* device) {
     Result res;
     AudioHwSync sync;
     ASSERT_OK(device->getHwAvSync(returnIn(res, sync)));
@@ -215,7 +234,7 @@
     ASSERT_OK(stream->updateSinkMetadata(initMetadata));
 
 #elif MAJOR_VERSION >= 7
-    xsdc_enum_range<android::audio::policy::configuration::V7_0::AudioSource> range;
+    xsdc_enum_range<android::audio::policy::configuration::CPP_VERSION::AudioSource> range;
     // Test all possible track configuration
     for (auto source : range) {
         for (float volume : {0.0, 0.5, 1.0}) {
@@ -272,8 +291,9 @@
     // Restore initial
     ASSERT_OK(stream->updateSourceMetadata(initMetadata));
 #elif MAJOR_VERSION >= 7
-    xsdc_enum_range<android::audio::policy::configuration::V7_0::AudioUsage> usageRange;
-    xsdc_enum_range<android::audio::policy::configuration::V7_0::AudioContentType> contentRange;
+    xsdc_enum_range<android::audio::policy::configuration::CPP_VERSION::AudioUsage> usageRange;
+    xsdc_enum_range<android::audio::policy::configuration::CPP_VERSION::AudioContentType>
+            contentRange;
     // Test all possible track configuration
     for (auto usage : usageRange) {
         for (auto content : contentRange) {
diff --git a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalUtils.h b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalUtils.h
index 81a1f7b..83ca9eb 100644
--- a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalUtils.h
+++ b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalUtils.h
@@ -14,33 +14,36 @@
  * limitations under the License.
  */
 
-#include PATH(android/hardware/audio/FILE_VERSION/IStream.h)
-#include PATH(android/hardware/audio/FILE_VERSION/types.h)
-#include PATH(android/hardware/audio/common/FILE_VERSION/types.h)
+// clang-format off
+#include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/IStreamIn.h)
+#include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/FILE_VERSION/IStreamOut.h)
+#include PATH(android/hardware/audio/common/COMMON_TYPES_FILE_VERSION/types.h)
+// clang-format on
 #include <hidl/HidlSupport.h>
 
 using ::android::hardware::hidl_bitfield;
 using ::android::hardware::hidl_handle;
 using ::android::hardware::hidl_string;
 using ::android::hardware::hidl_vec;
-using ::android::hardware::audio::common::CPP_VERSION::AudioChannelMask;
-using ::android::hardware::audio::common::CPP_VERSION::AudioFormat;
-using ::android::hardware::audio::CPP_VERSION::IStream;
-using ::android::hardware::audio::CPP_VERSION::ParameterValue;
-using ::android::hardware::audio::CPP_VERSION::Result;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::AudioChannelMask;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::AudioFormat;
+using ::android::hardware::audio::CORE_TYPES_CPP_VERSION::IStream;
+using ::android::hardware::audio::CORE_TYPES_CPP_VERSION::ParameterValue;
+using ::android::hardware::audio::CORE_TYPES_CPP_VERSION::Result;
 
 using namespace ::android::hardware::audio::common::test::utility;
 
-using Rotation = ::android::hardware::audio::CPP_VERSION::IPrimaryDevice::Rotation;
-using ::android::hardware::audio::common::CPP_VERSION::AudioContentType;
-using ::android::hardware::audio::common::CPP_VERSION::AudioUsage;
-using ::android::hardware::audio::CPP_VERSION::MicrophoneInfo;
+using Rotation = ::android::hardware::audio::CORE_TYPES_CPP_VERSION::IPrimaryDevice::Rotation;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::AudioContentType;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::AudioUsage;
+using ::android::hardware::audio::CORE_TYPES_CPP_VERSION::MicrophoneInfo;
 #if MAJOR_VERSION < 5
 using ::android::hardware::audio::CPP_VERSION::SinkMetadata;
 using ::android::hardware::audio::CPP_VERSION::SourceMetadata;
 #else
-using ::android::hardware::audio::common::CPP_VERSION::SinkMetadata;
-using ::android::hardware::audio::common::CPP_VERSION::SourceMetadata;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::SinkMetadata;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::SourceMetadata;
 #endif
 
 struct Parameters {
diff --git a/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
index 8af4c78..aef94da 100644
--- a/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
@@ -59,7 +59,8 @@
     testAccessors<OPTIONAL>(&OutputStreamTest::getStream, "dual mono mode",
                             Initial{DualMonoMode::OFF},
                             {DualMonoMode::LR, DualMonoMode::LL, DualMonoMode::RR},
-                            &IStreamOut::setDualMonoMode, &IStreamOut::getDualMonoMode);
+                            &::android::hardware::audio::CPP_VERSION::IStreamOut::setDualMonoMode,
+                            &::android::hardware::audio::CPP_VERSION::IStreamOut::getDualMonoMode);
 }
 
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DualMonoModeAccessorHidlTest);
@@ -73,7 +74,8 @@
     testAccessors<OPTIONAL>(
             &OutputStreamTest::getStream, "audio description mix level",
             Initial{-std::numeric_limits<float>::infinity()}, {-48.0f, -1.0f, 0.0f, 1.0f, 48.0f},
-            &IStreamOut::setAudioDescriptionMixLevel, &IStreamOut::getAudioDescriptionMixLevel,
+            &::android::hardware::audio::CPP_VERSION::IStreamOut::setAudioDescriptionMixLevel,
+            &::android::hardware::audio::CPP_VERSION::IStreamOut::getAudioDescriptionMixLevel,
             {48.5f, 1000.0f, std::numeric_limits<float>::infinity()});
 }
 
@@ -105,7 +107,8 @@
              PlaybackRate{0.5f, 0.5f, TimestretchMode::VOICE, TimestretchFallbackMode::MUTE},
              PlaybackRate{1000.0f, 1000.0f, TimestretchMode::VOICE, TimestretchFallbackMode::MUTE},
              PlaybackRate{1.0f, 1.0f, TimestretchMode::VOICE, TimestretchFallbackMode::FAIL}},
-            &IStreamOut::setPlaybackRateParameters, &IStreamOut::getPlaybackRateParameters,
+            &::android::hardware::audio::CPP_VERSION::IStreamOut::setPlaybackRateParameters,
+            &::android::hardware::audio::CPP_VERSION::IStreamOut::getPlaybackRateParameters,
             {PlaybackRate{1000.0f, 1000.0f, TimestretchMode::DEFAULT,
                           TimestretchFallbackMode::FAIL},
              PlaybackRate{1000.0f, 1000.0f, TimestretchMode::VOICE,
diff --git a/audio/core/all-versions/vts/functional/6.0/Generators.cpp b/audio/core/all-versions/vts/functional/6.0/Generators.cpp
index e3b98c9..dafd326 100644
--- a/audio/core/all-versions/vts/functional/6.0/Generators.cpp
+++ b/audio/core/all-versions/vts/functional/6.0/Generators.cpp
@@ -21,8 +21,8 @@
 #include "PolicyConfig.h"
 
 // clang-format off
-#include PATH(android/hardware/audio/FILE_VERSION/types.h)
-#include PATH(android/hardware/audio/common/FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/common/COMMON_TYPES_FILE_VERSION/types.h)
 // clang-format on
 
 // Forward declaration for functions that are substituted
@@ -30,7 +30,7 @@
 const PolicyConfig& getCachedPolicyConfig();
 const std::vector<DeviceParameter>& getDeviceParameters();
 
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
 using namespace ::android::hardware::audio::CPP_VERSION;
 
 std::vector<DeviceConfigParameter> generateOutputDeviceConfigParameters(bool oneProfilePerDevice) {
diff --git a/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
index 2759801..dfc2386 100644
--- a/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
@@ -53,9 +53,9 @@
 
 TEST_P(AudioHidlDeviceTest, SetConnectedStateInvalidDeviceAddress) {
     doc::test("Check that invalid device address is rejected by IDevice::setConnectedState");
-    EXPECT_RESULT(Result::INVALID_ARGUMENTS,
+    EXPECT_RESULT(invalidArgsOrNotSupported,
                   getDevice()->setConnectedState(getInvalidDeviceAddress(), true));
-    EXPECT_RESULT(Result::INVALID_ARGUMENTS,
+    EXPECT_RESULT(invalidArgsOrNotSupported,
                   getDevice()->setConnectedState(getInvalidDeviceAddress(), false));
 }
 
@@ -381,13 +381,13 @@
             "IDevice::open{Input|Output}Stream method.");
     AudioConfig suggestedConfig{};
     if (isParamForInputStream()) {
-        sp<IStreamIn> stream;
+        sp<::android::hardware::audio::CORE_TYPES_CPP_VERSION::IStreamIn> stream;
         ASSERT_OK(getDevice()->openInputStream(AudioIoHandle{}, getDeviceAddress(), getConfig(),
                                                getFlags(), getSinkMetadata(),
                                                returnIn(res, stream, suggestedConfig)));
         ASSERT_TRUE(stream == nullptr);
     } else {
-        sp<IStreamOut> stream;
+        sp<::android::hardware::audio::CORE_TYPES_CPP_VERSION::IStreamOut> stream;
         ASSERT_OK(getDevice()->openOutputStream(AudioIoHandle{}, getDeviceAddress(), getConfig(),
                                                 getFlags(), getSourceMetadata(),
                                                 returnIn(res, stream, suggestedConfig)));
@@ -551,13 +551,15 @@
     }
 
     void releasePatchIfNeeded() {
-        if (areAudioPatchesSupported()) {
-            if (mHasPatch) {
+        if (getDevice()) {
+            if (areAudioPatchesSupported() && mHasPatch) {
                 EXPECT_OK(getDevice()->releaseAudioPatch(mPatchHandle));
                 mHasPatch = false;
             }
         } else {
-            EXPECT_OK(stream->setDevices({address}));
+            if (stream) {
+                EXPECT_OK(stream->setDevices({address}));
+            }
         }
     }
 
@@ -713,7 +715,7 @@
             sink.base.channelMask.value(getConfig().base.channelMask);
             sink.ext.mix({});
             sink.ext.mix().ioHandle = helper.getIoHandle();
-            sink.ext.mix().useCase.source(toString(xsd::AudioSource::AUDIO_SOURCE_MIC));
+            sink.ext.mix().useCase.source(initMetadata.tracks[0].source);
             EXPECT_OK(getDevice()->createAudioPatch(hidl_vec<AudioPortConfig>{source},
                                                     hidl_vec<AudioPortConfig>{sink},
                                                     returnIn(res, mPatchHandle)));
@@ -724,13 +726,15 @@
     }
 
     void releasePatchIfNeeded() {
-        if (areAudioPatchesSupported()) {
-            if (mHasPatch) {
+        if (getDevice()) {
+            if (areAudioPatchesSupported() && mHasPatch) {
                 EXPECT_OK(getDevice()->releaseAudioPatch(mPatchHandle));
                 mHasPatch = false;
             }
         } else {
-            EXPECT_OK(stream->setDevices({address}));
+            if (stream) {
+                EXPECT_OK(stream->setDevices({address}));
+            }
         }
     }
 
diff --git a/audio/core/all-versions/vts/functional/7.0/Generators.cpp b/audio/core/all-versions/vts/functional/7.0/Generators.cpp
index 42bf1d3..f936d0a 100644
--- a/audio/core/all-versions/vts/functional/7.0/Generators.cpp
+++ b/audio/core/all-versions/vts/functional/7.0/Generators.cpp
@@ -20,20 +20,20 @@
 #include "7.0/PolicyConfig.h"
 
 // clang-format off
-#include PATH(android/hardware/audio/FILE_VERSION/types.h)
-#include PATH(android/hardware/audio/common/FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/common/COMMON_TYPES_FILE_VERSION/types.h)
 // clang-format on
 
-#include <android_audio_policy_configuration_V7_0-enums.h>
-#include <android_audio_policy_configuration_V7_0.h>
+#include PATH(APM_XSD_ENUMS_H_FILENAME)
+#include PATH(APM_XSD_H_FILENAME)
 
 // Forward declaration for functions that are substituted
 // in generator unit tests.
 const PolicyConfig& getCachedPolicyConfig();
 const std::vector<DeviceParameter>& getDeviceParameters();
 
-using namespace ::android::hardware::audio::common::CPP_VERSION;
-using namespace ::android::hardware::audio::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
+using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION;
 namespace xsd {
 using namespace ::android::audio::policy::configuration::CPP_VERSION;
 }
diff --git a/audio/core/all-versions/vts/functional/7.0/PolicyConfig.cpp b/audio/core/all-versions/vts/functional/7.0/PolicyConfig.cpp
index 2988207..d674403 100644
--- a/audio/core/all-versions/vts/functional/7.0/PolicyConfig.cpp
+++ b/audio/core/all-versions/vts/functional/7.0/PolicyConfig.cpp
@@ -30,9 +30,9 @@
 using ::android::NO_ERROR;
 using ::android::OK;
 
-using namespace ::android::hardware::audio::common::CPP_VERSION;
-using namespace ::android::hardware::audio::CPP_VERSION;
-using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
+using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::HidlUtils;
 using ::android::hardware::audio::common::utils::splitString;
 namespace xsd {
 using namespace ::android::audio::policy::configuration::CPP_VERSION;
diff --git a/audio/core/all-versions/vts/functional/7.0/PolicyConfig.h b/audio/core/all-versions/vts/functional/7.0/PolicyConfig.h
index f798839..4aea503 100644
--- a/audio/core/all-versions/vts/functional/7.0/PolicyConfig.h
+++ b/audio/core/all-versions/vts/functional/7.0/PolicyConfig.h
@@ -25,15 +25,15 @@
 #include <utils/Errors.h>
 
 // clang-format off
-#include PATH(android/hardware/audio/FILE_VERSION/types.h)
-#include PATH(android/hardware/audio/common/FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/common/COMMON_TYPES_FILE_VERSION/types.h)
 // clang-format on
 
-#include <android_audio_policy_configuration_V7_0-enums.h>
-#include <android_audio_policy_configuration_V7_0.h>
+#include PATH(APM_XSD_ENUMS_H_FILENAME)
+#include PATH(APM_XSD_H_FILENAME)
 
-using namespace ::android::hardware::audio::common::CPP_VERSION;
-using namespace ::android::hardware::audio::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
+using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION;
 namespace xsd {
 using namespace ::android::audio::policy::configuration::CPP_VERSION;
 using Module = Modules::Module;
diff --git a/audio/core/all-versions/vts/functional/7.1/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/7.1/AudioPrimaryHidlHalTest.cpp
new file mode 100644
index 0000000..d82d4ad
--- /dev/null
+++ b/audio/core/all-versions/vts/functional/7.1/AudioPrimaryHidlHalTest.cpp
@@ -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.
+ */
+
+// pull in all the <= 7.0 tests
+#include "7.0/AudioPrimaryHidlHalTest.cpp"
+
+TEST_P(AudioHidlDeviceTest, SetConnectedState_7_1) {
+    doc::test("Check that the HAL can be notified of device connection and disconnection");
+    using AD = xsd::AudioDevice;
+    for (auto deviceType : {AD::AUDIO_DEVICE_OUT_HDMI, AD::AUDIO_DEVICE_OUT_WIRED_HEADPHONE,
+                            AD::AUDIO_DEVICE_IN_USB_HEADSET}) {
+        SCOPED_TRACE("device=" + toString(deviceType));
+        for (bool state : {true, false}) {
+            SCOPED_TRACE("state=" + ::testing::PrintToString(state));
+            DeviceAddress address = {};
+            address.deviceType = toString(deviceType);
+            if (deviceType == AD::AUDIO_DEVICE_IN_USB_HEADSET) {
+                address.address.alsa({0, 0});
+            }
+            AudioPort devicePort;
+            devicePort.ext.device(address);
+            auto ret = getDevice()->setConnectedState_7_1(devicePort, state);
+            ASSERT_TRUE(ret.isOk());
+            if (ret == Result::NOT_SUPPORTED) {
+                doc::partialTest("setConnectedState_7_1 is not supported");
+                break;  // other deviceType might be supported
+            }
+            ASSERT_OK(ret);
+        }
+    }
+
+    // Because there is no way of knowing if the devices were connected before
+    // calling setConnectedState, there is no way to restore the HAL to its
+    // initial state. To workaround this, destroy the HAL at the end of this test.
+    ASSERT_TRUE(resetDevice());
+}
diff --git a/audio/core/all-versions/vts/functional/Android.bp b/audio/core/all-versions/vts/functional/Android.bp
index cfee26a..3007f01 100644
--- a/audio/core/all-versions/vts/functional/Android.bp
+++ b/audio/core/all-versions/vts/functional/Android.bp
@@ -48,6 +48,9 @@
 cc_test {
     name: "VtsHalAudioV2_0TargetTest",
     defaults: ["VtsHalAudioTargetTest_defaults"],
+    tidy_timeout_srcs: [
+        "2.0/AudioPrimaryHidlHalTest.cpp",
+    ],
     srcs: [
         "2.0/AudioPrimaryHidlHalTest.cpp",
     ],
@@ -74,6 +77,9 @@
 cc_test {
     name: "VtsHalAudioV4_0TargetTest",
     defaults: ["VtsHalAudioTargetTest_defaults"],
+    tidy_timeout_srcs: [
+        "4.0/AudioPrimaryHidlHalTest.cpp",
+    ],
     srcs: [
         "4.0/AudioPrimaryHidlHalTest.cpp",
     ],
@@ -126,6 +132,9 @@
 cc_test {
     name: "VtsHalAudioV6_0TargetTest",
     defaults: ["VtsHalAudioTargetTest_defaults"],
+    tidy_timeout_srcs: [
+        "6.0/AudioPrimaryHidlHalTest.cpp",
+    ],
     srcs: [
         "6.0/AudioPrimaryHidlHalTest.cpp",
         "6.0/Generators.cpp",
@@ -153,6 +162,9 @@
 cc_test {
     name: "VtsHalAudioV7_0TargetTest",
     defaults: ["VtsHalAudioTargetTest_defaults"],
+    tidy_timeout_srcs: [
+        "7.0/AudioPrimaryHidlHalTest.cpp",
+    ],
     srcs: [
         "7.0/AudioPrimaryHidlHalTest.cpp",
         "7.0/Generators.cpp",
@@ -179,6 +191,39 @@
     test_config: "VtsHalAudioV7_0TargetTest.xml",
 }
 
+cc_test {
+    name: "VtsHalAudioV7_1TargetTest",
+    defaults: ["VtsHalAudioTargetTest_defaults"],
+    srcs: [
+        "7.1/AudioPrimaryHidlHalTest.cpp",
+        "7.0/Generators.cpp",
+        "7.0/PolicyConfig.cpp",
+    ],
+    generated_headers: ["audio_policy_configuration_V7_1_parser"],
+    generated_sources: ["audio_policy_configuration_V7_1_parser"],
+    static_libs: [
+        "android.hardware.audio@7.0",
+        "android.hardware.audio@7.1",
+        "android.hardware.audio.common@7.0",
+        "android.hardware.audio.common@7.0-enums",
+        "android.hardware.audio.common@7.1-enums",
+        "android.hardware.audio.common@7.1-util",
+    ],
+    cflags: [
+        "-DMAJOR_VERSION=7",
+        "-DMINOR_VERSION=1",
+        "-DCOMMON_TYPES_MINOR_VERSION=0",
+        "-DCORE_TYPES_MINOR_VERSION=0",
+        "-include common/all-versions/VersionMacro.h",
+    ],
+    data: [
+        ":audio_policy_configuration_V7_1",
+    ],
+    // Use test_config for vts suite.
+    // TODO(b/146104851): Add auto-gen rules and remove it.
+    test_config: "VtsHalAudioV7_1TargetTest.xml",
+}
+
 // Note: the following aren't VTS tests, but rather unit tests
 // to verify correctness of test utilities.
 cc_test {
diff --git a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
index 340903a..61d447d 100644
--- a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
+++ b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
@@ -34,18 +34,21 @@
 
 #include <hwbinder/IPCThreadState.h>
 
+#include <android-base/expected.h>
 #include <android-base/logging.h>
 #include <system/audio_config.h>
 
+// clang-format off
 #include PATH(android/hardware/audio/FILE_VERSION/IDevice.h)
 #include PATH(android/hardware/audio/FILE_VERSION/IDevicesFactory.h)
 #include PATH(android/hardware/audio/FILE_VERSION/IPrimaryDevice.h)
-#include PATH(android/hardware/audio/FILE_VERSION/types.h)
-#include PATH(android/hardware/audio/common/FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/common/COMMON_TYPES_FILE_VERSION/types.h)
 #if MAJOR_VERSION >= 7
-#include <android_audio_policy_configuration_V7_0-enums.h>
-#include <android_audio_policy_configuration_V7_0.h>
+#include PATH(APM_XSD_ENUMS_H_FILENAME)
+#include PATH(APM_XSD_H_FILENAME)
 #endif
+// clang-format on
 
 #include <fmq/EventFlag.h>
 #include <fmq/MessageQueue.h>
@@ -86,11 +89,12 @@
 using ::android::hardware::audio::common::utils::mkEnumBitfield;
 using ::android::hardware::details::toHexString;
 
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
 using namespace ::android::hardware::audio::common::test::utility;
 using namespace ::android::hardware::audio::CPP_VERSION;
-using ReadParameters = ::android::hardware::audio::CPP_VERSION::IStreamIn::ReadParameters;
-using ReadStatus = ::android::hardware::audio::CPP_VERSION::IStreamIn::ReadStatus;
+using ReadParameters =
+        ::android::hardware::audio::CORE_TYPES_CPP_VERSION::IStreamIn::ReadParameters;
+using ReadStatus = ::android::hardware::audio::CORE_TYPES_CPP_VERSION::IStreamIn::ReadStatus;
 using WriteCommand = ::android::hardware::audio::CPP_VERSION::IStreamOut::WriteCommand;
 using WriteStatus = ::android::hardware::audio::CPP_VERSION::IStreamOut::WriteStatus;
 #if MAJOR_VERSION >= 7
@@ -124,6 +128,36 @@
 
 class HidlTest : public ::testing::Test {
   public:
+    using IDevice = ::android::hardware::audio::CPP_VERSION::IDevice;
+    using IDevicesFactory = ::android::hardware::audio::CPP_VERSION::IDevicesFactory;
+
+    static android::base::expected<std::vector<std::string>, std::string> getAllFactoryInstances() {
+        using ::android::hardware::audio::CPP_VERSION::IDevicesFactory;
+        const std::string factoryDescriptor = IDevicesFactory::descriptor;
+        // Make sure that the instance is the exact minor version.
+        // Using a 7.1 factory for 7.0 test is not always possible because
+        // 7.1 can be configured via the XML config to use features that are
+        // absent in 7.0.
+        auto instances = ::android::hardware::getAllHalInstanceNames(factoryDescriptor);
+        if (instances.empty()) return instances;
+        // Use the default instance for checking the implementation version.
+        auto defaultInstance = IDevicesFactory::getService("default");
+        if (defaultInstance == nullptr) {
+            return ::android::base::unexpected("Failed to obtain IDevicesFactory/default");
+        }
+        std::string actualDescriptor;
+        auto intDescRet = defaultInstance->interfaceDescriptor(
+                [&](const auto& descriptor) { actualDescriptor = descriptor; });
+        if (!intDescRet.isOk()) {
+            return ::android::base::unexpected("Failed to obtain interface descriptor: " +
+                                               intDescRet.description());
+        }
+        if (factoryDescriptor == actualDescriptor)
+            return instances;
+        else
+            return {};
+    }
+
     virtual ~HidlTest() = default;
     // public access to avoid annoyances when using this method in template classes
     // derived from test classes
@@ -168,8 +202,11 @@
 }
 
 TEST(CheckConfig, audioPolicyConfigurationValidation) {
-    const auto factories = ::android::hardware::getAllHalInstanceNames(IDevicesFactory::descriptor);
-    if (factories.size() == 0) {
+    const auto factories = HidlTest::getAllFactoryInstances();
+    if (!factories.ok()) {
+        FAIL() << factories.error();
+    }
+    if (factories.value().size() == 0) {
         GTEST_SKIP() << "Skipping audioPolicyConfigurationValidation because no factory instances "
                         "are found.";
     }
@@ -198,11 +235,11 @@
 const std::vector<DeviceParameter>& getDeviceParameters() {
     static std::vector<DeviceParameter> parameters = [] {
         std::vector<DeviceParameter> result;
-        const auto factories =
-                ::android::hardware::getAllHalInstanceNames(IDevicesFactory::descriptor);
+        const auto factories = HidlTest::getAllFactoryInstances();
+        if (!factories.ok()) return result;
         const auto devices = getCachedPolicyConfig().getModulesWithDevicesNames();
         result.reserve(devices.size());
-        for (const auto& factoryName : factories) {
+        for (const auto& factoryName : factories.value()) {
             for (const auto& deviceName : devices) {
                 if (DeviceManager::getInstance().get(factoryName, deviceName) != nullptr) {
                     result.emplace_back(factoryName, deviceName);
@@ -217,9 +254,9 @@
 const std::vector<DeviceParameter>& getDeviceParametersForFactoryTests() {
     static std::vector<DeviceParameter> parameters = [] {
         std::vector<DeviceParameter> result;
-        const auto factories =
-                ::android::hardware::getAllHalInstanceNames(IDevicesFactory::descriptor);
-        for (const auto& factoryName : factories) {
+        const auto factories = HidlTest::getAllFactoryInstances();
+        if (!factories.ok()) return result;
+        for (const auto& factoryName : factories.value()) {
             result.emplace_back(factoryName,
                                 DeviceManager::getInstance().getPrimary(factoryName) != nullptr
                                         ? DeviceManager::kPrimaryDevice
@@ -288,6 +325,8 @@
 // Test audio devices factory
 class AudioHidlTest : public AudioHidlTestWithDeviceParameter {
   public:
+    using IPrimaryDevice = ::android::hardware::audio::CPP_VERSION::IPrimaryDevice;
+
     void SetUp() override {
         ASSERT_NO_FATAL_FAILURE(AudioHidlTestWithDeviceParameter::SetUp());  // setup base
         ASSERT_TRUE(getDevicesFactory() != nullptr);
@@ -301,7 +340,7 @@
 TEST_P(AudioHidlTest, OpenDeviceInvalidParameter) {
     doc::test("Test passing an invalid parameter to openDevice");
     Result result;
-    sp<IDevice> device;
+    sp<::android::hardware::audio::CORE_TYPES_CPP_VERSION::IDevice> device;
 #if MAJOR_VERSION == 2
     auto invalidDevice = IDevicesFactory::Device(-1);
 #elif MAJOR_VERSION >= 4
@@ -572,8 +611,8 @@
                     [](auto&& arg) -> std::string {
                         using T = std::decay_t<decltype(arg)>;
                         // Need to use FQN of toString to avoid confusing the compiler
-                        return ::android::hardware::audio::common::CPP_VERSION::toString<T>(
-                                hidl_bitfield<T>(arg));
+                        return ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::
+                                toString<T>(hidl_bitfield<T>(arg));
                     },
                     std::get<PARAM_FLAGS>(info.param)));
 #elif MAJOR_VERSION >= 7
@@ -890,6 +929,8 @@
 
 class StreamWriter : public StreamWorker<StreamWriter> {
   public:
+    using IStreamOut = ::android::hardware::audio::CPP_VERSION::IStreamOut;
+
     StreamWriter(IStreamOut* stream, size_t bufferSize)
         : mStream(stream), mBufferSize(bufferSize), mData(mBufferSize) {}
     ~StreamWriter() {
@@ -998,7 +1039,8 @@
     EventFlag* mEfGroup = nullptr;
 };
 
-class OutputStreamTest : public OpenStreamTest<IStreamOut> {
+class OutputStreamTest
+    : public OpenStreamTest<::android::hardware::audio::CPP_VERSION::IStreamOut> {
     void SetUp() override {
         ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp());  // setup base
 #if MAJOR_VERSION <= 6
@@ -1012,9 +1054,12 @@
                 [&](AudioIoHandle handle, AudioConfig config, auto cb) {
 #if MAJOR_VERSION == 2
                     return getDevice()->openOutputStream(handle, address, config, flags, cb);
-#elif MAJOR_VERSION >= 4
+#elif MAJOR_VERSION >= 4 && (MAJOR_VERSION < 7 || (MAJOR_VERSION == 7 && MINOR_VERSION == 0))
                     return getDevice()->openOutputStream(handle, address, config, flags,
                                                          initMetadata, cb);
+#elif MAJOR_VERSION == 7 && MINOR_VERSION == 1
+                    return getDevice()->openOutputStream_7_1(handle, address, config, flags,
+                                                             initMetadata, cb);
 #endif
                 },
                 config);
@@ -1075,6 +1120,8 @@
 
 class StreamReader : public StreamWorker<StreamReader> {
   public:
+    using IStreamIn = ::android::hardware::audio::CORE_TYPES_CPP_VERSION::IStreamIn;
+
     StreamReader(IStreamIn* stream, size_t bufferSize)
         : mStream(stream), mBufferSize(bufferSize), mData(mBufferSize) {}
     ~StreamReader() {
@@ -1188,26 +1235,34 @@
     EventFlag* mEfGroup = nullptr;
 };
 
-class InputStreamTest : public OpenStreamTest<IStreamIn> {
+class InputStreamTest
+    : public OpenStreamTest<::android::hardware::audio::CORE_TYPES_CPP_VERSION::IStreamIn> {
     void SetUp() override {
         ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp());  // setup base
+        auto flags = getInputFlags();
 #if MAJOR_VERSION <= 6
         address.device = AudioDevice::IN_DEFAULT;
 #elif MAJOR_VERSION >= 7
         auto maybeSourceAddress = getCachedPolicyConfig().getSourceDeviceForMixPort(
                 getDeviceName(), getMixPortName());
+        auto& metadata = initMetadata.tracks[0];
         if (maybeSourceAddress.has_value() &&
             !xsd::isTelephonyDevice(maybeSourceAddress.value().deviceType)) {
             address = maybeSourceAddress.value();
-            auto& metadata = initMetadata.tracks[0];
             metadata.source = toString(xsd::AudioSource::AUDIO_SOURCE_UNPROCESSED);
             metadata.channelMask = getConfig().base.channelMask;
         } else {
             address.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_IN_DEFAULT);
         }
-#endif
+#if MAJOR_VERSION == 7 && MINOR_VERSION >= 1
+        auto flagsIt = std::find(flags.begin(), flags.end(),
+                                 toString(xsd::AudioInOutFlag::AUDIO_INPUT_FLAG_ULTRASOUND));
+        if (flagsIt != flags.end()) {
+            metadata.source = toString(xsd::AudioSource::AUDIO_SOURCE_ULTRASOUND);
+        }
+#endif  // 7.1
+#endif  // MAJOR_VERSION >= 7
         const AudioConfig& config = getConfig();
-        auto flags = getInputFlags();
         testOpen(
                 [&](AudioIoHandle handle, AudioConfig config, auto cb) {
                     return getDevice()->openInputStream(handle, address, config, flags,
@@ -1584,7 +1639,9 @@
                             "InputStream::setGain");
 }
 
-static void testPrepareForReading(IStreamIn* stream, uint32_t frameSize, uint32_t framesCount) {
+static void testPrepareForReading(
+        ::android::hardware::audio::CORE_TYPES_CPP_VERSION::IStreamIn* stream, uint32_t frameSize,
+        uint32_t framesCount) {
     Result res;
     // Ignore output parameters as the call should fail
     ASSERT_OK(stream->prepareForReading(frameSize, framesCount,
@@ -1655,7 +1712,8 @@
                             "setVolume");
 }
 
-static void testPrepareForWriting(IStreamOut* stream, uint32_t frameSize, uint32_t framesCount) {
+static void testPrepareForWriting(::android::hardware::audio::CPP_VERSION::IStreamOut* stream,
+                                  uint32_t frameSize, uint32_t framesCount) {
     Result res;
     // Ignore output parameters as the call should fail
     ASSERT_OK(stream->prepareForWriting(frameSize, framesCount,
@@ -1682,6 +1740,8 @@
 }
 
 struct Capability {
+    using IStreamOut = ::android::hardware::audio::CPP_VERSION::IStreamOut;
+
     Capability(IStreamOut* stream) {
         EXPECT_OK(stream->supportsPauseAndResume(returnIn(pause, resume)));
         drain = extract(stream->supportsDrain());
@@ -1725,7 +1785,7 @@
     Return<void> onError() override { return {}; }
 };
 
-static bool isAsyncModeSupported(IStreamOut* stream) {
+static bool isAsyncModeSupported(::android::hardware::audio::CPP_VERSION::IStreamOut* stream) {
     auto res = stream->setCallback(new MockOutCallbacks);
     stream->clearCallback();  // try to restore the no callback state, ignore
                               // any error
@@ -1780,7 +1840,8 @@
     ASSERT_RESULT(Result::INVALID_STATE, stream->pause());
 }
 
-static void testDrain(IStreamOut* stream, AudioDrain type) {
+static void testDrain(::android::hardware::audio::CPP_VERSION::IStreamOut* stream,
+                      AudioDrain type) {
     if (!Capability(stream).drain) {
         doc::partialTest("The output stream does not support drain");
         return;
@@ -1866,7 +1927,8 @@
 }
 
 using TtyModeAccessorPrimaryHidlTest =
-        AccessorHidlTest<IPrimaryDevice::TtyMode, AudioPrimaryHidlTest>;
+        AccessorHidlTest<::android::hardware::audio::CPP_VERSION::IPrimaryDevice::TtyMode,
+                         AudioPrimaryHidlTest>;
 TEST_P(TtyModeAccessorPrimaryHidlTest, setGetTtyMode) {
     doc::test("Query and set the TTY mode state");
     testAccessors<OPTIONAL>(
diff --git a/audio/core/all-versions/vts/functional/AudioTestDefinitions.h b/audio/core/all-versions/vts/functional/AudioTestDefinitions.h
index aa67630..802b87b 100644
--- a/audio/core/all-versions/vts/functional/AudioTestDefinitions.h
+++ b/audio/core/all-versions/vts/functional/AudioTestDefinitions.h
@@ -22,8 +22,8 @@
 #include <vector>
 
 // clang-format off
-#include PATH(android/hardware/audio/FILE_VERSION/types.h)
-#include PATH(android/hardware/audio/common/FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/common/COMMON_TYPES_FILE_VERSION/types.h)
 // clang-format on
 
 enum { PARAM_FACTORY_NAME, PARAM_DEVICE_NAME };
@@ -34,14 +34,14 @@
 #if MAJOR_VERSION <= 6
 enum { PARAM_DEVICE, PARAM_CONFIG, PARAM_FLAGS };
 enum { INDEX_INPUT, INDEX_OUTPUT };
-using DeviceConfigParameter =
-        std::tuple<DeviceParameter, android::hardware::audio::common::CPP_VERSION::AudioConfig,
-                   std::variant<android::hardware::audio::common::CPP_VERSION::AudioInputFlag,
-                                android::hardware::audio::common::CPP_VERSION::AudioOutputFlag>>;
+using DeviceConfigParameter = std::tuple<
+        DeviceParameter, android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::AudioConfig,
+        std::variant<android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::AudioInputFlag,
+                     android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::AudioOutputFlag>>;
 #elif MAJOR_VERSION >= 7
 enum { PARAM_DEVICE, PARAM_PORT_NAME, PARAM_CONFIG, PARAM_FLAGS };
 using DeviceConfigParameter =
         std::tuple<DeviceParameter, std::string,
-                   android::hardware::audio::common::CPP_VERSION::AudioConfig,
-                   std::vector<android::hardware::audio::CPP_VERSION::AudioInOutFlag>>;
+                   android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::AudioConfig,
+                   std::vector<android::hardware::audio::CORE_TYPES_CPP_VERSION::AudioInOutFlag>>;
 #endif
diff --git a/audio/core/all-versions/vts/functional/ConfigHelper.h b/audio/core/all-versions/vts/functional/ConfigHelper.h
index a2bb1ee..e4008cf 100644
--- a/audio/core/all-versions/vts/functional/ConfigHelper.h
+++ b/audio/core/all-versions/vts/functional/ConfigHelper.h
@@ -21,8 +21,8 @@
 #include "PolicyConfig.h"
 
 // clang-format off
-#include PATH(android/hardware/audio/FILE_VERSION/types.h)
-#include PATH(android/hardware/audio/common/FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/common/COMMON_TYPES_FILE_VERSION/types.h)
 // clang-format on
 
 using ::android::hardware::audio::common::utils::EnumBitfield;
diff --git a/audio/core/all-versions/vts/functional/DeviceManager.h b/audio/core/all-versions/vts/functional/DeviceManager.h
index 6db78a7..6bb39ed 100644
--- a/audio/core/all-versions/vts/functional/DeviceManager.h
+++ b/audio/core/all-versions/vts/functional/DeviceManager.h
@@ -22,19 +22,21 @@
 
 #include <android-base/logging.h>
 #include <hwbinder/IPCThreadState.h>
+#include <system/audio.h>
 
 // clang-format off
 #include PATH(android/hardware/audio/FILE_VERSION/IDevice.h)
 #include PATH(android/hardware/audio/FILE_VERSION/IDevicesFactory.h)
 #include PATH(android/hardware/audio/FILE_VERSION/IPrimaryDevice.h)
-#include PATH(android/hardware/audio/FILE_VERSION/types.h)
-#include PATH(android/hardware/audio/common/FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/common/COMMON_TYPES_FILE_VERSION/types.h)
 // clang-format on
 
 #include "utility/ReturnIn.h"
 
 using ::android::sp;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using ::android::hardware::audio::CORE_TYPES_CPP_VERSION::Result;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
 using namespace ::android::hardware::audio::common::test::utility;
 using namespace ::android::hardware::audio::CPP_VERSION;
 
@@ -94,29 +96,81 @@
     }
 };
 
-using FactoryAndDevice = std::tuple<std::string, std::string>;
-class DeviceManager : public InterfaceManager<DeviceManager, FactoryAndDevice, IDevice> {
+namespace impl {
+
+class PrimaryDeviceManager
+    : public InterfaceManager<PrimaryDeviceManager, std::string, IPrimaryDevice> {
   public:
-    static DeviceManager& getInstance() {
-        static DeviceManager instance;
-        return instance;
+    static sp<IPrimaryDevice> createInterfaceInstance(const std::string& factoryName) {
+        sp<IDevicesFactory> factory = DevicesFactoryManager::getInstance().get(factoryName);
+        return openPrimaryDevice(factory);
     }
+
+    bool reset(const std::string& factoryName) __attribute__((warn_unused_result)) {
+#if MAJOR_VERSION <= 5
+        return InterfaceManager::reset(factoryName, true);
+#elif MAJOR_VERSION >= 6
+        {
+            sp<IPrimaryDevice> device = getExisting(factoryName);
+            if (device != nullptr) {
+                auto ret = device->close();
+                ALOGE_IF(!ret.isOk(), "PrimaryDevice %s close failed: %s", factoryName.c_str(),
+                         ret.description().c_str());
+            }
+        }
+        return InterfaceManager::reset(factoryName, false);
+#endif
+    }
+
+  private:
+    static sp<IPrimaryDevice> openPrimaryDevice(const sp<IDevicesFactory>& factory) {
+        if (factory == nullptr) return {};
+        Result result;
+        sp<IPrimaryDevice> primaryDevice;
+#if !(MAJOR_VERSION == 7 && MINOR_VERSION == 1)
+        sp<IDevice> device;
+#if MAJOR_VERSION == 2
+        auto ret = factory->openDevice(IDevicesFactory::Device::PRIMARY, returnIn(result, device));
+        if (ret.isOk() && result == Result::OK && device != nullptr) {
+            primaryDevice = IPrimaryDevice::castFrom(device);
+        }
+#elif MAJOR_VERSION >= 4
+        auto ret = factory->openPrimaryDevice(returnIn(result, device));
+        if (ret.isOk() && result == Result::OK && device != nullptr) {
+            primaryDevice = IPrimaryDevice::castFrom(device);
+        }
+#endif
+        if (!ret.isOk() || result != Result::OK || primaryDevice == nullptr) {
+            ALOGW("Primary device can not be opened, transaction: %s, result %d, device %p",
+                  ret.description().c_str(), result, device.get());
+            return nullptr;
+        }
+#else  // V7.1
+        auto ret = factory->openPrimaryDevice_7_1(returnIn(result, primaryDevice));
+        if (!ret.isOk() || result != Result::OK) {
+            ALOGW("Primary device can not be opened, transaction: %s, result %d",
+                  ret.description().c_str(), result);
+            return nullptr;
+        }
+#endif
+        return primaryDevice;
+    }
+};
+
+using FactoryAndDevice = std::tuple<std::string, std::string>;
+class RegularDeviceManager
+    : public InterfaceManager<RegularDeviceManager, FactoryAndDevice, IDevice> {
+  public:
     static sp<IDevice> createInterfaceInstance(const FactoryAndDevice& factoryAndDevice) {
         auto [factoryName, name] = factoryAndDevice;
         sp<IDevicesFactory> factory = DevicesFactoryManager::getInstance().get(factoryName);
-        return name == kPrimaryDevice ? openPrimaryDevice(factory) : openDevice(factory, name);
+        return openDevice(factory, name);
     }
-    using InterfaceManager::reset;
-
-    static constexpr const char* kPrimaryDevice = "primary";
 
     sp<IDevice> get(const std::string& factoryName, const std::string& name) {
         return InterfaceManager::get(std::make_tuple(factoryName, name));
     }
-    sp<IPrimaryDevice> getPrimary(const std::string& factoryName) {
-        sp<IDevice> device = get(factoryName, kPrimaryDevice);
-        return device != nullptr ? IPrimaryDevice::castFrom(device) : nullptr;
-    }
+
     bool reset(const std::string& factoryName, const std::string& name)
             __attribute__((warn_unused_result)) {
 #if MAJOR_VERSION <= 5
@@ -133,42 +187,92 @@
         return InterfaceManager::reset(std::make_tuple(factoryName, name), false);
 #endif
     }
-    bool resetPrimary(const std::string& factoryName) __attribute__((warn_unused_result)) {
-        return reset(factoryName, kPrimaryDevice);
-    }
 
   private:
     static sp<IDevice> openDevice(const sp<IDevicesFactory>& factory, const std::string& name) {
         if (factory == nullptr) return nullptr;
-        sp<IDevice> device;
-#if MAJOR_VERSION >= 4
         Result result;
+        sp<IDevice> device;
+#if MAJOR_VERSION == 2
+        IDevicesFactory::Device dev = IDevicesFactory::IDevicesFactory::Device(-1);
+        if (name == AUDIO_HARDWARE_MODULE_ID_A2DP) {
+            dev = IDevicesFactory::Device::A2DP;
+        } else if (name == AUDIO_HARDWARE_MODULE_ID_USB) {
+            dev = IDevicesFactory::Device::USB;
+        } else if (name == AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX) {
+            dev = IDevicesFactory::Device::R_SUBMIX;
+        } else if (name == AUDIO_HARDWARE_MODULE_ID_STUB) {
+            dev = IDevicesFactory::Device::STUB;
+        }
+        auto ret = factory->openDevice(dev, returnIn(result, device));
+#elif MAJOR_VERSION >= 4 && (MAJOR_VERSION < 7 || (MAJOR_VERSION == 7 && MINOR_VERSION == 0))
         auto ret = factory->openDevice(name, returnIn(result, device));
+#elif MAJOR_VERSION == 7 && MINOR_VERSION == 1
+        auto ret = factory->openDevice_7_1(name, returnIn(result, device));
+#endif
         if (!ret.isOk() || result != Result::OK || device == nullptr) {
             ALOGW("Device %s can not be opened, transaction: %s, result %d, device %p",
                   name.c_str(), ret.description().c_str(), result, device.get());
             return nullptr;
         }
-#else
-        (void)name;
-#endif
         return device;
     }
+};
+
+}  // namespace impl
+
+class DeviceManager {
+  public:
+    static DeviceManager& getInstance() {
+        static DeviceManager instance;
+        return instance;
+    }
 
-    static sp<IDevice> openPrimaryDevice(const sp<IDevicesFactory>& factory) {
-        if (factory == nullptr) return nullptr;
-        Result result;
-        sp<IDevice> device;
-#if MAJOR_VERSION == 2
-        auto ret = factory->openDevice(IDevicesFactory::Device::PRIMARY, returnIn(result, device));
-#elif MAJOR_VERSION >= 4
-        auto ret = factory->openPrimaryDevice(returnIn(result, device));
-#endif
-        if (!ret.isOk() || result != Result::OK || device == nullptr) {
-            ALOGW("Primary device can not be opened, transaction: %s, result %d, device %p",
-                  ret.description().c_str(), result, device.get());
+    static constexpr const char* kPrimaryDevice = "primary";
+
+    sp<IDevice> get(const std::string& factoryName, const std::string& name) {
+        if (name == kPrimaryDevice) {
+            auto primary = getPrimary(factoryName);
+            return primary ? deviceFromPrimary(primary) : nullptr;
+        }
+        return mDevices.get(factoryName, name);
+    }
+
+    sp<IPrimaryDevice> getPrimary(const std::string& factoryName) {
+        return mPrimary.get(factoryName);
+    }
+
+    bool reset(const std::string& factoryName, const std::string& name)
+            __attribute__((warn_unused_result)) {
+        return name == kPrimaryDevice ? resetPrimary(factoryName)
+                                      : mDevices.reset(factoryName, name);
+    }
+
+    bool resetPrimary(const std::string& factoryName) __attribute__((warn_unused_result)) {
+        return mPrimary.reset(factoryName);
+    }
+
+    static void waitForInstanceDestruction() {
+        // Does not matter which device manager to use.
+        impl::RegularDeviceManager::waitForInstanceDestruction();
+    }
+
+  private:
+    sp<IDevice> deviceFromPrimary(const sp<IPrimaryDevice>& primary) {
+#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
+        auto ret = primary->getDevice();
+        if (ret.isOk()) {
+            return ret;
+        } else {
+            ALOGW("Error retrieving IDevice from primary: transaction: %s, primary %p",
+                  ret.description().c_str(), primary.get());
             return nullptr;
         }
-        return device;
+#else
+        return primary;
+#endif
     }
+
+    impl::PrimaryDeviceManager mPrimary;
+    impl::RegularDeviceManager mDevices;
 };
diff --git a/audio/core/all-versions/vts/functional/OWNERS b/audio/core/all-versions/vts/functional/OWNERS
new file mode 100644
index 0000000..448d9fe
--- /dev/null
+++ b/audio/core/all-versions/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 48436
+mnaganov@google.com
diff --git a/audio/core/all-versions/vts/functional/VtsHalAudioV7_1TargetTest.xml b/audio/core/all-versions/vts/functional/VtsHalAudioV7_1TargetTest.xml
new file mode 100644
index 0000000..7ce1477
--- /dev/null
+++ b/audio/core/all-versions/vts/functional/VtsHalAudioV7_1TargetTest.xml
@@ -0,0 +1,39 @@
+<?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 VtsHalAudioV7_1TargetTest.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-native" />
+
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+    <target_preparer class="com.android.tradefed.targetprep.StopServicesSetup"/>
+
+    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+        <option name="run-command" value="setprop vts.native_server.on 1"/>
+        <option name="teardown-command" value="setprop vts.native_server.on 0"/>
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="VtsHalAudioV7_1TargetTest->/data/local/tmp/VtsHalAudioV7_1TargetTest" />
+        <option name="push" value="audio_policy_configuration_V7_1.xsd->/data/local/tmp/audio_policy_configuration_V7_1.xsd" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="VtsHalAudioV7_1TargetTest" />
+        <option name="native-test-timeout" value="10m" />
+    </test>
+</configuration>
diff --git a/audio/core/all-versions/vts/functional/tests/generators_tests.cpp b/audio/core/all-versions/vts/functional/tests/generators_tests.cpp
index 3fdd8e6..76bf93e 100644
--- a/audio/core/all-versions/vts/functional/tests/generators_tests.cpp
+++ b/audio/core/all-versions/vts/functional/tests/generators_tests.cpp
@@ -33,7 +33,7 @@
 #endif
 
 using namespace android;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
 #if MAJOR_VERSION == 7
 namespace xsd {
 using namespace ::android::audio::policy::configuration::CPP_VERSION;
diff --git a/audio/effect/all-versions/OWNERS b/audio/effect/all-versions/OWNERS
index 24071af..f9a2d6b 100644
--- a/audio/effect/all-versions/OWNERS
+++ b/audio/effect/all-versions/OWNERS
@@ -1,2 +1,3 @@
+# Bug component: 48436
 elaurent@google.com
 mnaganov@google.com
diff --git a/audio/effect/all-versions/default/Android.bp b/audio/effect/all-versions/default/Android.bp
index 6df9dbf..1e01ffb 100644
--- a/audio/effect/all-versions/default/Android.bp
+++ b/audio/effect/all-versions/default/Android.bp
@@ -45,7 +45,6 @@
     header_libs: [
         "android.hardware.audio.common.util@all-versions",
         "libaudio_system_headers",
-        "libaudioclient_headers",
         "libeffects_headers",
         "libhardware_headers",
         "libmedia_headers",
diff --git a/audio/effect/all-versions/default/Effect.cpp b/audio/effect/all-versions/default/Effect.cpp
index ccfc6b2..49f6bf2 100644
--- a/audio/effect/all-versions/default/Effect.cpp
+++ b/audio/effect/all-versions/default/Effect.cpp
@@ -42,9 +42,10 @@
 namespace implementation {
 
 #if MAJOR_VERSION <= 6
-using ::android::hardware::audio::common::CPP_VERSION::implementation::AudioChannelBitfield;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::
+        AudioChannelBitfield;
 #endif
-using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::HidlUtils;
 
 namespace {
 
diff --git a/audio/effect/all-versions/default/Effect.h b/audio/effect/all-versions/default/Effect.h
index d5218f7..f9a6796 100644
--- a/audio/effect/all-versions/default/Effect.h
+++ b/audio/effect/all-versions/default/Effect.h
@@ -48,9 +48,10 @@
 using ::android::hardware::Return;
 using ::android::hardware::Void;
 #if MAJOR_VERSION <= 6
-using ::android::hardware::audio::common::CPP_VERSION::implementation::AudioDeviceBitfield;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::
+        AudioDeviceBitfield;
 #endif
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
 using namespace ::android::hardware::audio::effect::CPP_VERSION;
 
 struct Effect : public IEffect {
diff --git a/audio/effect/all-versions/default/EffectsFactory.cpp b/audio/effect/all-versions/default/EffectsFactory.cpp
index eb1cb49..e93ad89 100644
--- a/audio/effect/all-versions/default/EffectsFactory.cpp
+++ b/audio/effect/all-versions/default/EffectsFactory.cpp
@@ -53,7 +53,7 @@
 namespace CPP_VERSION {
 namespace implementation {
 
-using ::android::hardware::audio::common::CPP_VERSION::implementation::UuidUtils;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::UuidUtils;
 
 // static
 sp<IEffect> EffectsFactory::dispatchEffectInstanceCreation(const effect_descriptor_t& halDescriptor,
diff --git a/audio/effect/all-versions/default/EffectsFactory.h b/audio/effect/all-versions/default/EffectsFactory.h
index 0b86836..da16923 100644
--- a/audio/effect/all-versions/default/EffectsFactory.h
+++ b/audio/effect/all-versions/default/EffectsFactory.h
@@ -41,7 +41,7 @@
 using ::android::hardware::hidl_vec;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
 using namespace ::android::hardware::audio::effect::CPP_VERSION;
 
 struct EffectsFactory : public IEffectsFactory {
diff --git a/audio/effect/all-versions/default/EnvironmentalReverbEffect.h b/audio/effect/all-versions/default/EnvironmentalReverbEffect.h
index 9694b5d..001774d 100644
--- a/audio/effect/all-versions/default/EnvironmentalReverbEffect.h
+++ b/audio/effect/all-versions/default/EnvironmentalReverbEffect.h
@@ -43,7 +43,7 @@
 using ::android::hardware::hidl_vec;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
 using namespace ::android::hardware::audio::effect::CPP_VERSION;
 
 struct EnvironmentalReverbEffect : public IEnvironmentalReverbEffect {
diff --git a/audio/effect/all-versions/default/EqualizerEffect.h b/audio/effect/all-versions/default/EqualizerEffect.h
index 7a6bc0a..c4d76c1 100644
--- a/audio/effect/all-versions/default/EqualizerEffect.h
+++ b/audio/effect/all-versions/default/EqualizerEffect.h
@@ -43,7 +43,7 @@
 using ::android::hardware::hidl_vec;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
 using namespace ::android::hardware::audio::effect::CPP_VERSION;
 
 struct EqualizerEffect : public IEqualizerEffect {
diff --git a/audio/effect/all-versions/default/LoudnessEnhancerEffect.h b/audio/effect/all-versions/default/LoudnessEnhancerEffect.h
index 6d80207..122ec36 100644
--- a/audio/effect/all-versions/default/LoudnessEnhancerEffect.h
+++ b/audio/effect/all-versions/default/LoudnessEnhancerEffect.h
@@ -39,7 +39,7 @@
 using ::android::hardware::hidl_vec;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
 using namespace ::android::hardware::audio::effect::CPP_VERSION;
 
 struct LoudnessEnhancerEffect : public ILoudnessEnhancerEffect {
diff --git a/audio/effect/all-versions/default/NoiseSuppressionEffect.h b/audio/effect/all-versions/default/NoiseSuppressionEffect.h
index 6cc45b9..96b9ecf 100644
--- a/audio/effect/all-versions/default/NoiseSuppressionEffect.h
+++ b/audio/effect/all-versions/default/NoiseSuppressionEffect.h
@@ -41,7 +41,7 @@
 using ::android::hardware::hidl_vec;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
 using namespace ::android::hardware::audio::effect::CPP_VERSION;
 
 struct NoiseSuppressionEffect : public INoiseSuppressionEffect {
diff --git a/audio/effect/all-versions/default/PresetReverbEffect.h b/audio/effect/all-versions/default/PresetReverbEffect.h
index eb55e20..9d82c08 100644
--- a/audio/effect/all-versions/default/PresetReverbEffect.h
+++ b/audio/effect/all-versions/default/PresetReverbEffect.h
@@ -39,7 +39,7 @@
 using ::android::hardware::hidl_vec;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
 using namespace ::android::hardware::audio::effect::CPP_VERSION;
 
 struct PresetReverbEffect : public IPresetReverbEffect {
diff --git a/audio/effect/all-versions/default/VirtualizerEffect.cpp b/audio/effect/all-versions/default/VirtualizerEffect.cpp
index 1dce181..6efc4ea 100644
--- a/audio/effect/all-versions/default/VirtualizerEffect.cpp
+++ b/audio/effect/all-versions/default/VirtualizerEffect.cpp
@@ -34,7 +34,7 @@
 namespace CPP_VERSION {
 namespace implementation {
 
-using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::HidlUtils;
 
 VirtualizerEffect::VirtualizerEffect(effect_handle_t handle)
     : mEffect(new Effect(false /*isInput*/, handle)) {}
diff --git a/audio/effect/all-versions/default/VirtualizerEffect.h b/audio/effect/all-versions/default/VirtualizerEffect.h
index 3ed06d1..f26e4fa 100644
--- a/audio/effect/all-versions/default/VirtualizerEffect.h
+++ b/audio/effect/all-versions/default/VirtualizerEffect.h
@@ -40,9 +40,10 @@
 using ::android::hardware::Return;
 using ::android::hardware::Void;
 #if MAJOR_VERSION <= 6
-using ::android::hardware::audio::common::CPP_VERSION::implementation::AudioChannelBitfield;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::
+        AudioChannelBitfield;
 #endif
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
 using namespace ::android::hardware::audio::effect::CPP_VERSION;
 
 struct VirtualizerEffect : public IVirtualizerEffect {
diff --git a/audio/effect/all-versions/default/VisualizerEffect.h b/audio/effect/all-versions/default/VisualizerEffect.h
index 3ae4b08..b8424c4 100644
--- a/audio/effect/all-versions/default/VisualizerEffect.h
+++ b/audio/effect/all-versions/default/VisualizerEffect.h
@@ -39,7 +39,7 @@
 using ::android::hardware::hidl_vec;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
 using namespace ::android::hardware::audio::effect::CPP_VERSION;
 
 struct VisualizerEffect : public IVisualizerEffect {
diff --git a/audio/effect/all-versions/default/util/EffectUtils.cpp b/audio/effect/all-versions/default/util/EffectUtils.cpp
index 1156d21..296f84d 100644
--- a/audio/effect/all-versions/default/util/EffectUtils.cpp
+++ b/audio/effect/all-versions/default/util/EffectUtils.cpp
@@ -25,8 +25,8 @@
 
 #include "util/EffectUtils.h"
 
-using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
-using ::android::hardware::audio::common::CPP_VERSION::implementation::UuidUtils;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::HidlUtils;
+using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::UuidUtils;
 using ::android::hardware::audio::common::utils::EnumBitfield;
 
 namespace android {
@@ -36,7 +36,7 @@
 namespace CPP_VERSION {
 namespace implementation {
 
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
 
 #define CONVERT_CHECKED(expr, result)                   \
     if (status_t status = (expr); status != NO_ERROR) { \
diff --git a/audio/effect/all-versions/default/util/tests/effectutils_tests.cpp b/audio/effect/all-versions/default/util/tests/effectutils_tests.cpp
index d021fa0..adfa167 100644
--- a/audio/effect/all-versions/default/util/tests/effectutils_tests.cpp
+++ b/audio/effect/all-versions/default/util/tests/effectutils_tests.cpp
@@ -27,7 +27,7 @@
 #include <xsdc/XsdcSupport.h>
 
 using namespace android;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
 using namespace ::android::hardware::audio::effect::CPP_VERSION;
 using ::android::hardware::audio::effect::CPP_VERSION::implementation::EffectUtils;
 namespace xsd {
diff --git a/audio/effect/all-versions/vts/functional/Android.bp b/audio/effect/all-versions/vts/functional/Android.bp
index 48d6474..3b15ed4 100644
--- a/audio/effect/all-versions/vts/functional/Android.bp
+++ b/audio/effect/all-versions/vts/functional/Android.bp
@@ -26,6 +26,9 @@
 cc_defaults {
     name: "VtsHalAudioEffectTargetTest_default",
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: [
+        "VtsHalAudioEffectTargetTest.cpp",
+    ],
     srcs: [
         "VtsHalAudioEffectTargetTest.cpp",
         "ValidateAudioEffectsConfiguration.cpp",
diff --git a/audio/effect/all-versions/vts/functional/OWNERS b/audio/effect/all-versions/vts/functional/OWNERS
new file mode 100644
index 0000000..448d9fe
--- /dev/null
+++ b/audio/effect/all-versions/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 48436
+mnaganov@google.com
diff --git a/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp b/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp
index 23e7786..e59423f 100644
--- a/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp
+++ b/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp
@@ -50,7 +50,7 @@
 using ::android::hardware::audio::common::utils::mkEnumBitfield;
 using ::android::hidl::allocator::V1_0::IAllocator;
 using ::android::hidl::memory::V1_0::IMemory;
-using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
 using namespace ::android::hardware::audio::effect::CPP_VERSION;
 #if MAJOR_VERSION >= 7
 // Make an alias for enumerations generated from the APM config XSD.
diff --git a/audio/policy/1.0/vts/functional/OWNERS b/audio/policy/1.0/vts/functional/OWNERS
new file mode 100644
index 0000000..448d9fe
--- /dev/null
+++ b/audio/policy/1.0/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 48436
+mnaganov@google.com
diff --git a/authsecret/1.0/vts/functional/OWNERS b/authsecret/1.0/vts/functional/OWNERS
new file mode 100644
index 0000000..ec8c304
--- /dev/null
+++ b/authsecret/1.0/vts/functional/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 186411
+chengyouho@google.com
+frankwoo@google.com
diff --git a/authsecret/aidl/default/Android.bp b/authsecret/aidl/default/Android.bp
index a6c0bc4..7ce83fd 100644
--- a/authsecret/aidl/default/Android.bp
+++ b/authsecret/aidl/default/Android.bp
@@ -34,7 +34,7 @@
         "AuthSecret.cpp",
     ],
     shared_libs: [
-        "android.hardware.authsecret-V1-ndk_platform",
+        "android.hardware.authsecret-V1-ndk",
         "libbase",
         "libbinder_ndk",
     ],
diff --git a/authsecret/aidl/default/service.cpp b/authsecret/aidl/default/service.cpp
index efecf10..a7d8678 100644
--- a/authsecret/aidl/default/service.cpp
+++ b/authsecret/aidl/default/service.cpp
@@ -28,7 +28,7 @@
 
     const std::string instance = std::string() + AuthSecret::descriptor + "/default";
     binder_status_t status = AServiceManager_addService(authsecret->asBinder().get(), instance.c_str());
-    CHECK(status == STATUS_OK);
+    CHECK_EQ(status, STATUS_OK);
 
     ABinderProcess_joinThreadPool();
     return -1; // Should never be reached
diff --git a/authsecret/aidl/vts/Android.bp b/authsecret/aidl/vts/Android.bp
index dca7046..5ec9947 100644
--- a/authsecret/aidl/vts/Android.bp
+++ b/authsecret/aidl/vts/Android.bp
@@ -30,7 +30,7 @@
         "use_libaidlvintf_gtest_helper_static",
     ],
     srcs: ["VtsHalAuthSecretTargetTest.cpp"],
-    static_libs: ["android.hardware.authsecret-V1-ndk_platform"],
+    static_libs: ["android.hardware.authsecret-V1-ndk"],
     shared_libs: ["libbinder_ndk"],
     test_suites: [
         "general-tests",
diff --git a/automotive/audiocontrol/1.0/vts/functional/OWNERS b/automotive/audiocontrol/1.0/vts/functional/OWNERS
new file mode 100644
index 0000000..fb422db
--- /dev/null
+++ b/automotive/audiocontrol/1.0/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 162915
+zhaomingyin@google.com
diff --git a/automotive/audiocontrol/2.0/vts/functional/OWNERS b/automotive/audiocontrol/2.0/vts/functional/OWNERS
new file mode 100644
index 0000000..fb422db
--- /dev/null
+++ b/automotive/audiocontrol/2.0/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 162915
+zhaomingyin@google.com
diff --git a/automotive/audiocontrol/aidl/Android.bp b/automotive/audiocontrol/aidl/Android.bp
index 4acfd82..623097c 100644
--- a/automotive/audiocontrol/aidl/Android.bp
+++ b/automotive/audiocontrol/aidl/Android.bp
@@ -13,11 +13,17 @@
     name: "android.hardware.automotive.audiocontrol",
     vendor_available: true,
     srcs: ["android/hardware/automotive/audiocontrol/*.aidl"],
+    imports: [
+        "android.media.audio.common.types",
+        "android.hardware.audio.common",
+    ],
     stability: "vintf",
     backend: {
         java: {
-            sdk_version: "module_current",
+            platform_apis: true,
         },
     },
-    versions: ["1"],
+    versions: [
+        "1",
+    ],
 }
diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioFocusChange.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioFocusChange.aidl
index 3dc393a..58a3667 100644
--- a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioFocusChange.aidl
+++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioFocusChange.aidl
@@ -1,14 +1,30 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// 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 changes to the AIDL files built
+// 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
diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioGainConfigInfo.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioGainConfigInfo.aidl
new file mode 100644
index 0000000..fb6ac65
--- /dev/null
+++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/AudioGainConfigInfo.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.automotive.audiocontrol;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable AudioGainConfigInfo {
+  int zoneId;
+  String devicePortAddress;
+  int volumeIndex;
+}
diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/DuckingInfo.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/DuckingInfo.aidl
index 6d729e2..23abb46 100644
--- a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/DuckingInfo.aidl
+++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/DuckingInfo.aidl
@@ -1,14 +1,30 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// 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 changes to the AIDL files built
+// 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
@@ -22,4 +38,5 @@
   String[] deviceAddressesToDuck;
   String[] deviceAddressesToUnduck;
   String[] usagesHoldingFocus;
+  @nullable android.hardware.audio.common.PlaybackTrackMetadata[] playbackMetaDataHoldingFocus;
 }
diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IAudioControl.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IAudioControl.aidl
index bc4162b..8dc5ffe 100644
--- a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IAudioControl.aidl
+++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IAudioControl.aidl
@@ -1,14 +1,30 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// 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 changes to the AIDL files built
+// 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
@@ -18,10 +34,16 @@
 package android.hardware.automotive.audiocontrol;
 @VintfStability
 interface IAudioControl {
+  /**
+   * @deprecated use {@link android.hardware.audio.common.PlaybackTrackMetadata} instead.
+   */
   oneway void onAudioFocusChange(in String usage, in int zoneId, in android.hardware.automotive.audiocontrol.AudioFocusChange focusChange);
   oneway void onDevicesToDuckChange(in android.hardware.automotive.audiocontrol.DuckingInfo[] duckingInfos);
   oneway void onDevicesToMuteChange(in android.hardware.automotive.audiocontrol.MutingInfo[] mutingInfos);
   oneway void registerFocusListener(in android.hardware.automotive.audiocontrol.IFocusListener listener);
   oneway void setBalanceTowardRight(in float value);
   oneway void setFadeTowardFront(in float value);
+  oneway void onAudioFocusChangeWithMetaData(in android.hardware.audio.common.PlaybackTrackMetadata playbackMetaData, in int zoneId, in android.hardware.automotive.audiocontrol.AudioFocusChange focusChange);
+  oneway void setAudioDeviceGainsChanged(in android.hardware.automotive.audiocontrol.Reasons[] reasons, in android.hardware.automotive.audiocontrol.AudioGainConfigInfo[] gains);
+  oneway void registerGainCallback(in android.hardware.automotive.audiocontrol.IAudioGainCallback callback);
 }
diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IAudioGainCallback.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IAudioGainCallback.aidl
new file mode 100644
index 0000000..17a087f
--- /dev/null
+++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IAudioGainCallback.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.automotive.audiocontrol;
+@VintfStability
+interface IAudioGainCallback {
+  oneway void onAudioDeviceGainsChanged(in android.hardware.automotive.audiocontrol.Reasons[] reasons, in android.hardware.automotive.audiocontrol.AudioGainConfigInfo[] gains);
+}
diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IFocusListener.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IFocusListener.aidl
index f00f042..3e17552 100644
--- a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IFocusListener.aidl
+++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IFocusListener.aidl
@@ -1,14 +1,30 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// 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 changes to the AIDL files built
+// 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
@@ -20,4 +36,6 @@
 interface IFocusListener {
   oneway void abandonAudioFocus(in String usage, in int zoneId);
   oneway void requestAudioFocus(in String usage, in int zoneId, in android.hardware.automotive.audiocontrol.AudioFocusChange focusGain);
+  oneway void abandonAudioFocusWithMetaData(in android.hardware.audio.common.PlaybackTrackMetadata playbackMetaData, in int zoneId);
+  oneway void requestAudioFocusWithMetaData(in android.hardware.audio.common.PlaybackTrackMetadata playbackMetaData, in int zoneId, in android.hardware.automotive.audiocontrol.AudioFocusChange focusGain);
 }
diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/MutingInfo.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/MutingInfo.aidl
index ab902ec..b25ed0f 100644
--- a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/MutingInfo.aidl
+++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/MutingInfo.aidl
@@ -1,14 +1,30 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// 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 changes to the AIDL files built
+// 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
diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/Reasons.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/Reasons.aidl
new file mode 100644
index 0000000..c1e22d4
--- /dev/null
+++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/Reasons.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.automotive.audiocontrol;
+@Backing(type="int") @VintfStability
+enum Reasons {
+  FORCED_MASTER_MUTE = 1,
+  REMOTE_MUTE = 2,
+  TCU_MUTE = 4,
+  ADAS_DUCKING = 8,
+  NAV_DUCKING = 16,
+  PROJECTION_DUCKING = 32,
+  THERMAL_LIMITATION = 64,
+  SUSPEND_EXIT_VOL_LIMITATION = 128,
+  EXTERNAL_AMP_VOL_FEEDBACK = 256,
+  OTHER = -2147483648,
+}
diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioGainConfigInfo.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioGainConfigInfo.aidl
new file mode 100644
index 0000000..c938296
--- /dev/null
+++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/AudioGainConfigInfo.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.automotive.audiocontrol;
+
+/**
+ * NOTE:
+ * Was expecting to reuse android.media.audio types... Limit info to minimum to prevent
+ * duplicating aidl_api. Will follow up if AudioGainConfig is exposed by android.media AIDL API.
+ */
+@JavaDerive(equals=true, toString=true)
+@VintfStability
+parcelable AudioGainConfigInfo {
+    /**
+     * The identifier for the audio zone the audio device port associated to this gain belongs to.
+     *
+     */
+    int zoneId;
+
+    /**
+     * The Audio Output Device Port Address.
+     *
+     * This is the address that can be retrieved at JAVA layer using the introspection
+     * {@link android.media.AudioManager#listAudioDevicePorts} API then
+     * {@link audio.media.AudioDeviceInfo#getAddress} API.
+     *
+     * At HAL layer, it corresponds to audio_port_v7.audio_port_device_ext.address.
+     *
+     * Devices that does not have an address will indicate an empty string "".
+     */
+    String devicePortAddress;
+
+    /**
+     * UI Index of the corresponding AudioGain in AudioPort.gains.
+     */
+    int volumeIndex;
+}
diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/DuckingInfo.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/DuckingInfo.aidl
index e95fe9b..c30d5f6 100644
--- a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/DuckingInfo.aidl
+++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/DuckingInfo.aidl
@@ -14,7 +14,9 @@
  * limitations under the License.
  */
 
- package android.hardware.automotive.audiocontrol;
+package android.hardware.automotive.audiocontrol;
+
+import android.hardware.audio.common.PlaybackTrackMetadata;
 
  /**
   * The current ducking information for a single audio zone.
@@ -48,7 +50,15 @@
      /**
       * List of usages currently holding focus for this audio zone.
       *
+      * This field was deprecated in version 2.
+      * Use playbackMetaDataHoldingFocus instead.
+      *
       * <p> See {@code audioUsage} in audio_policy_configuration.xsd for the list of allowed values.
       */
      String[] usagesHoldingFocus;
- }
\ No newline at end of file
+
+     /**
+      *  List of output stream metadata associated with the current focus holder for this audio zone
+      */
+     @nullable PlaybackTrackMetadata[] playbackMetaDataHoldingFocus;
+}
diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IAudioControl.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IAudioControl.aidl
index 3a02245..100f1ba 100644
--- a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IAudioControl.aidl
+++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IAudioControl.aidl
@@ -20,6 +20,40 @@
 import android.hardware.automotive.audiocontrol.DuckingInfo;
 import android.hardware.automotive.audiocontrol.MutingInfo;
 import android.hardware.automotive.audiocontrol.IFocusListener;
+import android.hardware.automotive.audiocontrol.IAudioGainCallback;
+import android.hardware.automotive.audiocontrol.AudioGainConfigInfo;
+import android.hardware.automotive.audiocontrol.Reasons;
+
+/**
+ * Important note on Metadata:
+ * Metadata qualifies a playback track for an output stream.
+ * This is highly closed to {@link android.media.AudioAttributes}.
+ * It allows to identify the audio stream rendered / requesting / abandonning the focus.
+ *
+ * AudioControl 1.0 was limited to identification through {@code AttributeUsage} listed as
+ * {@code audioUsage} in audio_policy_configuration.xsd.
+ *
+ * Any new OEM needs would not be possible without extension.
+ *
+ * Relying on {@link android.hardware.automotive.audiocontrol.PlaybackTrackMetadata} allows
+ * to use a combination of {@code AttributeUsage}, {@code AttributeContentType} and
+ * {@code AttributeTags} to identify the use case / routing thanks to
+ * {@link android.media.audiopolicy.AudioProductStrategy}.
+ * The belonging to a strategy is deduced by an AOSP logic (in sync at native and java layer).
+ *
+ * IMPORTANT NOTE ON TAGS:
+ * To limit the possibilies and prevent from confusion, we expect the String to follow
+ * a given formalism that will be enforced.
+ *
+ * 1 / By convention, tags shall be a "key=value" pair.
+ * Vendor must namespace their tag's key (for example com.google.strategy=VR) to avoid conflicts.
+ * vendor specific applications and must be prefixed by "VX_". Vendor must
+ *
+ * 2 / Tags reported here shall be the same as the tags used to define a given
+ * {@link android.media.audiopolicy.AudioProductStrategy} and so in
+ * audio_policy_engine_configuration.xml file.
+ */
+import android.hardware.audio.common.PlaybackTrackMetadata;
 
 /**
  * Interacts with the car's audio subsystem to manage audio sources and volumes
@@ -36,8 +70,12 @@
      * The HAL is not required to wait for an callback of AUDIOFOCUS_GAIN before playing audio, nor
      * is it required to stop playing audio in the event of a AUDIOFOCUS_LOSS callback is received.
      *
+     * This method was deprecated in version 2 to allow getting rid of usages limitation.
+     * Use {@link IAudioControl#onAudioFocusChangeWithMetaData} instead.
+     *
      * @param usage The audio usage associated with the focus change {@code AttributeUsage}. See
      * {@code audioUsage} in audio_policy_configuration.xsd for the list of allowed values.
+     * @deprecated use {@link android.hardware.audio.common.PlaybackTrackMetadata} instead.
      * @param zoneId The identifier for the audio zone that the HAL is playing the stream in
      * @param focusChange the AudioFocusChange that has occurred.
      */
@@ -99,4 +137,51 @@
      * range.
      */
     oneway void setFadeTowardFront(in float value);
-}
\ No newline at end of file
+
+    /**
+     * Notifies HAL of changes in audio focus status for focuses requested or abandoned by the HAL.
+     *
+     * This will be called in response to IFocusListener's requestAudioFocus and
+     * abandonAudioFocus, as well as part of any change in focus being held by the HAL due focus
+     * request from other activities or services.
+     *
+     * The HAL is not required to wait for an callback of AUDIOFOCUS_GAIN before playing audio, nor
+     * is it required to stop playing audio in the event of a AUDIOFOCUS_LOSS callback is received.
+     *
+     * @param playbackMetaData The output stream metadata associated with the focus request
+     * @param zoneId The identifier for the audio zone that the HAL is playing the stream in
+     * @param focusChange the AudioFocusChange that has occurred.
+     */
+    oneway void onAudioFocusChangeWithMetaData(in PlaybackTrackMetadata playbackMetaData,
+        in int zoneId, in AudioFocusChange focusChange);
+
+     /**
+     * Notifies HAL of changes in output devices that the HAL should apply gain change to
+     * and the reason(s) why
+     *
+     * This may be called in response to changes in audio focus, and will include a list of
+     * {@link android.hardware.automotive.audiocontrol.AudioGainConfigInfo} objects per audio zone
+     * that experienced a change in audo focus.
+     *
+     * @param reasons List of reasons that triggered the given gains changed.
+     *                This must be one or more of the
+     *                {@link android.hardware.automotive.audiocontrol.Reasons} constants.
+     *
+     * @param gains List of gains the change is intended to.
+      */
+     oneway void setAudioDeviceGainsChanged(in Reasons[] reasons, in AudioGainConfigInfo[] gains);
+
+    /**
+     * Registers callback to be used by HAL for reporting unexpected gain(s) changed and the
+     * reason(s) why.
+     *
+     * It is expected that there will only ever be a single callback registered. If the
+     * observer dies, the HAL implementation must unregister observer automatically. If called when
+     * a listener is already registered, the existing one should be unregistered and replaced with
+     * the new callback.
+     *
+     * @param callback The {@link android.hardware.automotive.audiocontrol.IAudioGainCallback}
+     *                 interface.
+     */
+    oneway void registerGainCallback(in IAudioGainCallback callback);
+}
diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IAudioGainCallback.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IAudioGainCallback.aidl
new file mode 100644
index 0000000..17b4341
--- /dev/null
+++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IAudioGainCallback.aidl
@@ -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.
+ */
+
+package android.hardware.automotive.audiocontrol;
+
+import android.hardware.automotive.audiocontrol.AudioGainConfigInfo;
+import android.hardware.automotive.audiocontrol.Reasons;
+
+/**
+ * Interface definition for a callback to be invoked when the gain(s) of the device port(s) is(are)
+ * updated at HAL layer.
+ *
+ * <p>This defines counter part API of
+ * {@link android.hardware.automotive.audiocontrol.IAudioControl#onDevicesToDuckChange},
+ * {@link android.hardware.automotive.audiocontrol.IAudioControl#onDevicesToMuteChange} and
+ * {@link android.hardware.automotive.audiocontrol.IAudioControl#setAudioDeviceGainsChanged} APIs.
+ *
+ * The previous API defines Mute/Duck order decided by the client (e.g. CarAudioService)
+ * and delegated to AudioControl for application.
+ *
+ * This callback interface defines Mute/Duck notification decided by AudioControl HAL (due to
+ * e.g. - external conditions from Android IVI subsystem
+ *      - regulation / need faster decision rather than using
+ *        {@link android.hardware.automotive.audiocontrol.IAudioControl#onAudioFocusChange} to
+ *        report the use case and then waiting for CarAudioService decision to Mute/Duck.
+ */
+@VintfStability
+oneway interface IAudioGainCallback {
+    /**
+     * Used to indicated the one or more audio device port gains have changed unexpectidely, i.e.
+     * initiated by HAL, not by CarAudioService.
+     * This is the counter part of the
+     *      {@link android.hardware.automotive.audiocontrol.onDevicesToDuckChange},
+     *      {@link android.hardware.automotive.audiocontrol.onDevicesToMuteChange} and
+     *      {@link android.hardware.automotive.audiocontrol.setAudioDeviceGainsChanged} APIs.
+     *
+     * Flexibility is given to OEM to mute/duck in HAL or in CarAudioService.
+     * For critical use cases (i.e. when regulation is required), better to handle mute/duck in
+     * HAL layer and informs upper layer.
+     * Non critical use case may report gain and focus and CarAudioService to decide of duck/mute.
+     *
+     * @param reasons List of reasons that triggered the given gains changed.
+     *                This must be one or more of the
+     *                {@link android.hardware.automotive.audiocontrol.Reasons} constants.
+     *                It will define if the port has been muted/ducked or must now affected
+     *                by gain limitation that shall be notified/enforced at CarAudioService
+     *                layer.
+     *
+     * @param gains List of gains affected by the change.
+     */
+    void onAudioDeviceGainsChanged(in Reasons[] reasons, in AudioGainConfigInfo[] gains);
+}
diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IFocusListener.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IFocusListener.aidl
index b79295a..1ce1f40 100644
--- a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IFocusListener.aidl
+++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IFocusListener.aidl
@@ -18,10 +18,13 @@
 
 import android.hardware.automotive.audiocontrol.AudioFocusChange;
 
+import android.hardware.audio.common.PlaybackTrackMetadata;
+
 /**
  * Callback interface for audio focus listener.
  *
  * For typical configuration, the listener the car audio service.
+ *
  */
 @VintfStability
 interface IFocusListener {
@@ -33,6 +36,9 @@
      * interaction is oneway to avoid blocking HAL so that it is not required to wait for a response
      * before stopping audio playback.
      *
+     * Deprecated in version 2 to allow generic interface callback listener.
+     * Use {@link IFocusListener#abandonHalAudioFocusWithMetaData} instead.
+     *
      * @param usage The audio usage for which the HAL is abandoning focus {@code AttributeUsage}.
      * See {@code audioUsage} in audio_policy_configuration.xsd for the list of allowed values.
      * @param zoneId The identifier for the audio zone that the HAL abandoning focus
@@ -47,6 +53,9 @@
      * interaction is oneway to avoid blocking HAL so that it is not required to wait for a response
      * before playing audio.
      *
+     * Deprecated in version 2 to allow generic interface callback listener.
+     * Use {@link IFocusListener#requestAudioFocusWithMetaData} instead.
+     *
      * @param usage The audio usage associated with the focus request {@code AttributeUsage}. See
      * {@code audioUsage} in audio_policy_configuration.xsd for the list of allowed values.
      * @param zoneId The identifier for the audio zone where the HAL is requesting focus
@@ -54,4 +63,29 @@
      * following: GAIN, GAIN_TRANSIENT, GAIN_TRANSIENT_MAY_DUCK, GAIN_TRANSIENT_EXCLUSIVE.
      */
     oneway void requestAudioFocus(in String usage, in int zoneId, in AudioFocusChange focusGain);
-}
\ No newline at end of file
+
+    /**
+     * Used to indicate that the audio output stream associated with
+     * {@link android.hardware.audio.common.PlaybackTrackMetadata} has released
+     * the focus.
+     *
+     * @param playbackMetaData The output stream metadata associated with the focus request
+     * @param zoneId The identifier for the audio zone that the HAL abandoning focus
+     */
+    oneway void abandonAudioFocusWithMetaData(in PlaybackTrackMetadata playbackMetaData,
+            in int zoneId);
+
+    /**
+     * Used to indicate that the audio output stream associated with
+     * {@link android.hardware.audio.common.PlaybackTrackMetadata} has taken the focus.
+     *
+     * @param playbackMetaData The output stream metadata associated with the focus request
+     * @param zoneId The identifier for the audio zone that the HAL abandoning focus
+     * @param focusGain The focus type requested.
+     *                  This must be one of the
+     *                  {@link android.hardware.automotive.audiocontrol.AudioFocusChange}
+     *                  constants.
+     */
+    oneway void requestAudioFocusWithMetaData(in PlaybackTrackMetadata playbackMetaData,
+          in int zoneId, in AudioFocusChange focusGain);
+}
diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/Reasons.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/Reasons.aidl
new file mode 100644
index 0000000..3d9e8a2
--- /dev/null
+++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/Reasons.aidl
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.audiocontrol;
+
+/**
+ * Enum to identify the reason(s) of
+ * {@link android.hardware.automotive.audiocontrol.AudioGainConfigInfo} changed event
+ */
+@Backing(type="int")
+@VintfStability
+enum Reasons {
+    /**
+     * Magic Key Code (may be SWRC button combination) to force muting all audio sources.
+     * This may be used for example in case of cyber attach to ensure driver can safely drive back
+     * to garage to restore sw.
+     */
+    FORCED_MASTER_MUTE               = 0x1,
+    /**
+    * Reports a mute request outside the IVI (Android) system.
+    * It may target to mute the list of
+    * {@link android.hardware.automotive.audiocontrol.AudioGainConfigInfo}.
+    * A focus request may also be reported in addition if the use case that initiates the mute
+    * has matching {@link android.hardware.automotive.audiocontrol.PlaybackTrackMetadata}
+    * For regulation issue, the action of mute could be managed by HAL itself.
+     */
+    REMOTE_MUTE                     = 0x2,
+    /**
+    * Reports a mute initiated by the TCU. It may be applied to all audio source (no
+    * associated {@link android.hardware.automotive.audiocontrol.AudioGainConfigInfo} reported, or
+    * it may target to mute only the given list of ports.
+    * A focus request may also be reported in addition.
+    * For regulation issue, the action of mute could be managed by HAL itself.
+     */
+    TCU_MUTE                        = 0x4,
+    /**
+     * Reports a duck due to ADAS use case. A focus request may also be reported in addition.
+     * For regulation issue, the action of duck could be managed by HAL itself.
+     * It gives a chance to CarAudioService to decide whether contextual volume change may be
+     * applied from the ducked index base or not.
+     */
+    ADAS_DUCKING                    = 0x8,
+    /**
+     * Reports a duck due to navigation use case. It gives a chance to CarAudioService to decide
+     * whether contextual volume change may be applied from the ducked index base or not.
+     */
+    NAV_DUCKING                     = 0x10,
+    /**
+     * Some device projection stack may send signal to IVI to duck / unduck main audio stream.
+     * In this case, Contextual Volume Policy may be adapted to control the alternate / secondary
+     * audio stream.
+     */
+    PROJECTION_DUCKING              = 0x20,
+    /**
+     * When the amplifier is overheating, it may be recovered by limiting the volume.
+     */
+    THERMAL_LIMITATION              = 0x40,
+    /**
+     * Before the system enters suspend, it may ensure while exiting suspend or during cold boot
+     * that the volume is limited to prevent from sound explosion.
+     */
+    SUSPEND_EXIT_VOL_LIMITATION     = 0x80,
+    /**
+     * When using an external amplifier, it may be required to keep volume in sync and have
+     * asynchronous notification of effective volume change.
+     */
+    EXTERNAL_AMP_VOL_FEEDBACK       = 0x100,
+    /**
+     * For other OEM use.
+     */
+    OTHER                           = 0x80000000,
+}
diff --git a/automotive/audiocontrol/aidl/default/Android.bp b/automotive/audiocontrol/aidl/default/Android.bp
index 7694bdf..1439cce 100644
--- a/automotive/audiocontrol/aidl/default/Android.bp
+++ b/automotive/audiocontrol/aidl/default/Android.bp
@@ -29,8 +29,8 @@
     vendor: true,
     shared_libs: [
         "android.hardware.audio.common@7.0-enums",
-        "android.frameworks.automotive.powerpolicy-V1-ndk_platform",
-        "android.hardware.automotive.audiocontrol-V1-ndk_platform",
+        "android.frameworks.automotive.powerpolicy-V1-ndk",
+        "android.hardware.automotive.audiocontrol-V1-ndk",
         "libbase",
         "libbinder_ndk",
         "libcutils",
diff --git a/automotive/audiocontrol/aidl/default/main.cpp b/automotive/audiocontrol/aidl/default/main.cpp
index 9b259fc..cc15ccb 100644
--- a/automotive/audiocontrol/aidl/default/main.cpp
+++ b/automotive/audiocontrol/aidl/default/main.cpp
@@ -31,7 +31,7 @@
     const std::string instance = std::string() + AudioControl::descriptor + "/default";
     binder_status_t status =
             AServiceManager_addService(audioControl->asBinder().get(), instance.c_str());
-    CHECK(status == STATUS_OK);
+    CHECK_EQ(status, STATUS_OK);
 
     std::shared_ptr<PowerPolicyClient> powerPolicyClient =
             ::ndk::SharedRefBase::make<PowerPolicyClient>(audioControl);
diff --git a/automotive/can/1.0/default/Android.bp b/automotive/can/1.0/default/Android.bp
index 163fdb7..05691d9 100644
--- a/automotive/can/1.0/default/Android.bp
+++ b/automotive/can/1.0/default/Android.bp
@@ -46,13 +46,7 @@
     vendor: true,
     relative_install_path: "hw",
     srcs: [
-        "CanBus.cpp",
-        "CanBusNative.cpp",
-        "CanBusVirtual.cpp",
-        "CanBusSlcan.cpp",
-        "CanController.cpp",
-        "CanSocket.cpp",
-        "CloseHandle.cpp",
+        ":automotiveCanV1.0_sources",
         "service.cpp",
     ],
     shared_libs: [
@@ -66,3 +60,22 @@
     ],
     vintf_fragments: ["manifest_android.hardware.automotive.can@1.0.xml"],
 }
+
+filegroup {
+    name: "automotiveCanV1.0_sources",
+    srcs: [
+        "CanBus.cpp",
+        "CanBusNative.cpp",
+        "CanBusVirtual.cpp",
+        "CanBusSlcan.cpp",
+        "CanController.cpp",
+        "CanSocket.cpp",
+        "CloseHandle.cpp",
+    ],
+}
+
+cc_library_headers {
+    name: "automotiveCanV1.0_headers",
+    vendor: true,
+    export_include_dirs: ["."],
+}
diff --git a/automotive/can/1.0/default/tests/fuzzer/Android.bp b/automotive/can/1.0/default/tests/fuzzer/Android.bp
new file mode 100644
index 0000000..52b43b0
--- /dev/null
+++ b/automotive/can/1.0/default/tests/fuzzer/Android.bp
@@ -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 {
+    // 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_fuzz {
+    name: "automotiveCanV1.0_fuzzer",
+    vendor: true,
+    defaults: ["android.hardware.automotive.can@defaults"],
+    srcs: [
+        "AutomotiveCanV1_0Fuzzer.cpp",
+        ":automotiveCanV1.0_sources",
+    ],
+    header_libs: [
+        "automotiveCanV1.0_headers",
+        "android.hardware.automotive.can@hidl-utils-lib",
+    ],
+    shared_libs: [
+        "android.hardware.automotive.can@1.0",
+        "libhidlbase",
+    ],
+    static_libs: [
+        "android.hardware.automotive.can@libnetdevice",
+        "android.hardware.automotive@libc++fs",
+        "libnl++",
+    ],
+    fuzz_config: {
+        cc: [
+            "android-media-fuzzing-reports@google.com",
+        ],
+        componentid: 533764,
+    },
+}
diff --git a/automotive/can/1.0/default/tests/fuzzer/AutomotiveCanV1_0Fuzzer.cpp b/automotive/can/1.0/default/tests/fuzzer/AutomotiveCanV1_0Fuzzer.cpp
new file mode 100644
index 0000000..96110db
--- /dev/null
+++ b/automotive/can/1.0/default/tests/fuzzer/AutomotiveCanV1_0Fuzzer.cpp
@@ -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.
+ *
+ */
+#include "AutomotiveCanV1_0Fuzzer.h"
+
+namespace android::hardware::automotive::can::V1_0::implementation::fuzzer {
+
+constexpr CanController::InterfaceType kInterfaceType[] = {CanController::InterfaceType::VIRTUAL,
+                                                           CanController::InterfaceType::SOCKETCAN,
+                                                           CanController::InterfaceType::SLCAN};
+constexpr FilterFlag kFilterFlag[] = {FilterFlag::DONT_CARE, FilterFlag::SET, FilterFlag::NOT_SET};
+constexpr size_t kInterfaceTypeLength = std::size(kInterfaceType);
+constexpr size_t kFilterFlagLength = std::size(kFilterFlag);
+constexpr size_t kMaxCharacters = 30;
+constexpr size_t kMaxPayloadBytes = 64;
+constexpr size_t kMaxFilters = 20;
+constexpr size_t kMaxSerialNumber = 1000;
+constexpr size_t kMaxBuses = 10;
+constexpr size_t kMaxRepeat = 5;
+
+Bus CanFuzzer::makeBus() {
+    ICanController::BusConfig config = {};
+    if (mBusNames.size() > 0 && mLastInterface < mBusNames.size()) {
+        config.name = mBusNames[mLastInterface++];
+    } else {
+        config.name = mFuzzedDataProvider->ConsumeRandomLengthString(kMaxCharacters);
+    }
+    config.interfaceId.virtualif({mFuzzedDataProvider->ConsumeRandomLengthString(kMaxCharacters)});
+    return Bus(mCanController, config);
+}
+
+void CanFuzzer::getSupportedInterfaceTypes() {
+    hidl_vec<CanController::InterfaceType> iftypesResult;
+    mCanController->getSupportedInterfaceTypes(hidl_utils::fill(&iftypesResult));
+}
+
+hidl_vec<hidl_string> CanFuzzer::getBusNames() {
+    hidl_vec<hidl_string> services = {};
+    if (auto manager = hidl::manager::V1_2::IServiceManager::getService(); manager) {
+        manager->listManifestByInterface(ICanBus::descriptor, hidl_utils::fill(&services));
+    }
+    return services;
+}
+
+void CanFuzzer::invokeUpInterface() {
+    const CanController::InterfaceType iftype =
+            kInterfaceType[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(
+                    0, kInterfaceTypeLength - 1)];
+    std::string configName;
+
+    if (const bool shouldInvokeValidBus = mFuzzedDataProvider->ConsumeBool();
+        (shouldInvokeValidBus) && (mBusNames.size() > 0)) {
+        const size_t busNameIndex =
+                mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, mBusNames.size() - 1);
+        configName = mBusNames[busNameIndex];
+    } else {
+        configName = mFuzzedDataProvider->ConsumeRandomLengthString(kMaxCharacters);
+    }
+    const std::string ifname = mFuzzedDataProvider->ConsumeRandomLengthString(kMaxCharacters);
+
+    ICanController::BusConfig config = {.name = configName};
+
+    if (iftype == CanController::InterfaceType::SOCKETCAN) {
+        CanController::BusConfig::InterfaceId::Socketcan socketcan = {};
+        if (const bool shouldPassSerialSocket = mFuzzedDataProvider->ConsumeBool();
+            shouldPassSerialSocket) {
+            socketcan.serialno(
+                    {mFuzzedDataProvider->ConsumeIntegralInRange<uint32_t>(0, kMaxSerialNumber)});
+        } else {
+            socketcan.ifname(ifname);
+        }
+        config.interfaceId.socketcan(socketcan);
+    } else if (iftype == CanController::InterfaceType::SLCAN) {
+        CanController::BusConfig::InterfaceId::Slcan slcan = {};
+        if (const bool shouldPassSerialSlcan = mFuzzedDataProvider->ConsumeBool();
+            shouldPassSerialSlcan) {
+            slcan.serialno(
+                    {mFuzzedDataProvider->ConsumeIntegralInRange<uint32_t>(0, kMaxSerialNumber)});
+        } else {
+            slcan.ttyname(ifname);
+        }
+        config.interfaceId.slcan(slcan);
+    } else if (iftype == CanController::InterfaceType::VIRTUAL) {
+        config.interfaceId.virtualif({ifname});
+    }
+
+    const size_t numInvocations =
+            mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, kMaxRepeat);
+    for (size_t i = 0; i < numInvocations; ++i) {
+        mCanController->upInterface(config);
+    }
+}
+
+void CanFuzzer::invokeDownInterface() {
+    hidl_string configName;
+    if (const bool shouldInvokeValidBus = mFuzzedDataProvider->ConsumeBool();
+        (shouldInvokeValidBus) && (mBusNames.size() > 0)) {
+        const size_t busNameIndex =
+                mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, mBusNames.size() - 1);
+        configName = mBusNames[busNameIndex];
+    } else {
+        configName = mFuzzedDataProvider->ConsumeRandomLengthString(kMaxCharacters);
+    }
+
+    const size_t numInvocations =
+            mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, kMaxRepeat);
+    for (size_t i = 0; i < numInvocations; ++i) {
+        mCanController->downInterface(configName);
+    }
+}
+
+void CanFuzzer::invokeController() {
+    getSupportedInterfaceTypes();
+    invokeUpInterface();
+    invokeDownInterface();
+}
+
+void CanFuzzer::invokeBus() {
+    const size_t numBuses = mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(1, kMaxBuses);
+    for (size_t i = 0; i < numBuses; ++i) {
+        if (const bool shouldSendMessage = mFuzzedDataProvider->ConsumeBool(); shouldSendMessage) {
+            auto sendingBus = makeBus();
+            CanMessage msg = {.id = mFuzzedDataProvider->ConsumeIntegral<uint32_t>()};
+            uint32_t numPayloadBytes =
+                    mFuzzedDataProvider->ConsumeIntegralInRange<uint32_t>(0, kMaxPayloadBytes);
+            hidl_vec<uint8_t> payload(numPayloadBytes);
+            for (uint32_t j = 0; j < numPayloadBytes; ++j) {
+                payload[j] = mFuzzedDataProvider->ConsumeIntegral<uint32_t>();
+            }
+            msg.payload = payload;
+            msg.remoteTransmissionRequest = mFuzzedDataProvider->ConsumeBool();
+            msg.isExtendedId = mFuzzedDataProvider->ConsumeBool();
+            sendingBus.send(msg);
+        } else {
+            auto listeningBus = makeBus();
+            uint32_t numFilters =
+                    mFuzzedDataProvider->ConsumeIntegralInRange<uint32_t>(1, kMaxFilters);
+            hidl_vec<CanMessageFilter> filterVector(numFilters);
+            for (uint32_t k = 0; k < numFilters; ++k) {
+                filterVector[k].id = mFuzzedDataProvider->ConsumeIntegral<uint32_t>();
+                filterVector[k].mask = mFuzzedDataProvider->ConsumeIntegral<uint32_t>();
+                filterVector[k].rtr =
+                        kFilterFlag[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(
+                                0, kFilterFlagLength - 1)];
+                filterVector[k].extendedFormat =
+                        kFilterFlag[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(
+                                0, kFilterFlagLength - 1)];
+                filterVector[k].exclude = mFuzzedDataProvider->ConsumeBool();
+            }
+            auto listener = listeningBus.listen(filterVector);
+        }
+    }
+}
+
+void CanFuzzer::deInit() {
+    mCanController.clear();
+    if (mFuzzedDataProvider) {
+        delete mFuzzedDataProvider;
+    }
+    mBusNames = {};
+}
+
+void CanFuzzer::process(const uint8_t* data, size_t size) {
+    mFuzzedDataProvider = new FuzzedDataProvider(data, size);
+    invokeController();
+    invokeBus();
+}
+
+bool CanFuzzer::init() {
+    mCanController = sp<CanController>::make();
+    if (!mCanController) {
+        return false;
+    }
+    mBusNames = getBusNames();
+    return true;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    if (size < 1) {
+        return 0;
+    }
+    CanFuzzer canFuzzer;
+    if (canFuzzer.init()) {
+        canFuzzer.process(data, size);
+    }
+    return 0;
+}
+
+}  // namespace android::hardware::automotive::can::V1_0::implementation::fuzzer
diff --git a/automotive/can/1.0/default/tests/fuzzer/AutomotiveCanV1_0Fuzzer.h b/automotive/can/1.0/default/tests/fuzzer/AutomotiveCanV1_0Fuzzer.h
new file mode 100644
index 0000000..930cddd
--- /dev/null
+++ b/automotive/can/1.0/default/tests/fuzzer/AutomotiveCanV1_0Fuzzer.h
@@ -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.
+ *
+ */
+#ifndef __AUTOMOTIVE_CAN_V1_0_FUZZER_H__
+#define __AUTOMOTIVE_CAN_V1_0_FUZZER_H__
+#include <CanController.h>
+#include <android/hidl/manager/1.2/IServiceManager.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <hidl-utils/hidl-utils.h>
+
+namespace android::hardware::automotive::can::V1_0::implementation::fuzzer {
+
+using ::android::sp;
+
+struct CanMessageListener : public can::V1_0::ICanMessageListener {
+    DISALLOW_COPY_AND_ASSIGN(CanMessageListener);
+
+    CanMessageListener() {}
+
+    virtual Return<void> onReceive(const can::V1_0::CanMessage& msg) override {
+        std::unique_lock<std::mutex> lock(mMessagesGuard);
+        mMessages.push_back(msg);
+        mMessagesUpdated.notify_one();
+        return {};
+    }
+
+    virtual ~CanMessageListener() {
+        if (mCloseHandle) {
+            mCloseHandle->close();
+        }
+    }
+
+    void assignCloseHandle(sp<ICloseHandle> closeHandle) { mCloseHandle = closeHandle; }
+
+  private:
+    sp<ICloseHandle> mCloseHandle;
+
+    std::mutex mMessagesGuard;
+    std::condition_variable mMessagesUpdated GUARDED_BY(mMessagesGuard);
+    std::vector<can::V1_0::CanMessage> mMessages GUARDED_BY(mMessagesGuard);
+};
+
+struct Bus {
+    DISALLOW_COPY_AND_ASSIGN(Bus);
+
+    Bus(sp<ICanController> controller, const ICanController::BusConfig& config)
+        : mIfname(config.name), mController(controller) {
+        const auto result = controller->upInterface(config);
+        const auto manager = hidl::manager::V1_2::IServiceManager::getService();
+        const auto service = manager->get(ICanBus::descriptor, config.name);
+        mBus = ICanBus::castFrom(service);
+    }
+
+    virtual ~Bus() { reset(); }
+
+    void reset() {
+        mBus.clear();
+        if (mController) {
+            mController->downInterface(mIfname);
+            mController.clear();
+        }
+    }
+
+    ICanBus* operator->() const { return mBus.get(); }
+    sp<ICanBus> get() { return mBus; }
+
+    sp<CanMessageListener> listen(const hidl_vec<CanMessageFilter>& filter) {
+        sp<CanMessageListener> listener = sp<CanMessageListener>::make();
+
+        if (!mBus) {
+            return listener;
+        }
+        Result result;
+        sp<ICloseHandle> closeHandle;
+        mBus->listen(filter, listener, hidl_utils::fill(&result, &closeHandle)).assertOk();
+        listener->assignCloseHandle(closeHandle);
+
+        return listener;
+    }
+
+    void send(const CanMessage& msg) {
+        if (!mBus) {
+            return;
+        }
+        mBus->send(msg);
+    }
+
+  private:
+    const std::string mIfname;
+    sp<ICanController> mController;
+    sp<ICanBus> mBus;
+};
+
+class CanFuzzer {
+  public:
+    ~CanFuzzer() { deInit(); }
+    bool init();
+    void process(const uint8_t* data, size_t size);
+    void deInit();
+
+  private:
+    Bus makeBus();
+    hidl_vec<hidl_string> getBusNames();
+    void getSupportedInterfaceTypes();
+    void invokeBus();
+    void invokeController();
+    void invokeUpInterface();
+    void invokeDownInterface();
+    FuzzedDataProvider* mFuzzedDataProvider = nullptr;
+    sp<CanController> mCanController = nullptr;
+    hidl_vec<hidl_string> mBusNames = {};
+    unsigned mLastInterface = 0;
+};
+}  // namespace android::hardware::automotive::can::V1_0::implementation::fuzzer
+
+#endif  // __AUTOMOTIVE_CAN_V1_0_FUZZER_H__
diff --git a/automotive/can/1.0/vts/functional/OWNERS b/automotive/can/1.0/vts/functional/OWNERS
new file mode 100644
index 0000000..85257a3
--- /dev/null
+++ b/automotive/can/1.0/vts/functional/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 533426
+twasilczyk@google.com
+chrisweir@google.com
diff --git a/automotive/evs/1.0/vts/functional/OWNERS b/automotive/evs/1.0/vts/functional/OWNERS
new file mode 100644
index 0000000..ea4b613
--- /dev/null
+++ b/automotive/evs/1.0/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 853002
+changyeon@google.com
diff --git a/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp b/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
index ad607d8..9c72acd 100644
--- a/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
+++ b/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
@@ -18,7 +18,7 @@
 
 
 // These values are called out in the EVS design doc (as of Mar 8, 2017)
-static const int kMaxStreamStartMilliseconds = 500;
+static const int kMaxStreamStartMilliseconds = 1000;
 static const int kMinimumFramesPerSecond = 10;
 
 static const int kSecondsToMilliseconds = 1000;
@@ -332,11 +332,6 @@
         printf("Measured time to first frame %0.2f ms\n", timeToFirstFrame * kNanoToMilliseconds);
         ALOGI("Measured time to first frame %0.2f ms", timeToFirstFrame * kNanoToMilliseconds);
 
-        // Check aspect ratio
-        unsigned width = 0, height = 0;
-        frameHandler->getFrameDimension(&width, &height);
-        EXPECT_GE(width, height);
-
         // Wait a bit, then ensure we get at least the required minimum number of frames
         sleep(5);
         nsecs_t end = systemTime(SYSTEM_TIME_MONOTONIC);
@@ -370,7 +365,7 @@
     ALOGI("Starting CameraStreamBuffering test");
 
     // Arbitrary constant (should be > 1 and not too big)
-    static const unsigned int kBuffersToHold = 6;
+    static const unsigned int kBuffersToHold = 2;
 
     // Get the camera list
     loadCameraList();
diff --git a/automotive/evs/1.1/vts/functional/Android.bp b/automotive/evs/1.1/vts/functional/Android.bp
index cbc2150..18687bf 100644
--- a/automotive/evs/1.1/vts/functional/Android.bp
+++ b/automotive/evs/1.1/vts/functional/Android.bp
@@ -25,6 +25,9 @@
 
 cc_test {
     name: "VtsHalEvsV1_1TargetTest",
+    tidy_timeout_srcs: [
+        "VtsHalEvsV1_1TargetTest.cpp",
+    ],
     srcs: [
         "FrameHandler.cpp",
         "FrameHandlerUltrasonics.cpp",
diff --git a/automotive/evs/1.1/vts/functional/OWNERS b/automotive/evs/1.1/vts/functional/OWNERS
new file mode 100644
index 0000000..ea4b613
--- /dev/null
+++ b/automotive/evs/1.1/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 853002
+changyeon@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 1216d36..d7f9ff8 100644
--- a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
+++ b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
@@ -499,11 +499,6 @@
                   << std::scientific << timeToFirstFrame * kNanoToMilliseconds
                   << " ms.";
 
-        // Check aspect ratio
-        unsigned width = 0, height = 0;
-        frameHandler->getFrameDimension(&width, &height);
-        EXPECT_GE(width, height);
-
         // Wait a bit, then ensure we get at least the required minimum number of frames
         sleep(5);
         nsecs_t end = systemTime(SYSTEM_TIME_MONOTONIC);
@@ -541,7 +536,7 @@
     LOG(INFO) << "Starting CameraStreamBuffering test";
 
     // Arbitrary constant (should be > 1 and not too big)
-    static const unsigned int kBuffersToHold = 6;
+    static const unsigned int kBuffersToHold = 2;
 
     // Get the camera list
     loadCameraList();
diff --git a/automotive/evs/OWNERS b/automotive/evs/OWNERS
index 6fc5024..b973e91 100644
--- a/automotive/evs/OWNERS
+++ b/automotive/evs/OWNERS
@@ -1,3 +1,3 @@
+ankitarora@google.com
 changyeon@google.com
-garysungang@google.com
-haoxiangl@google.com
+jwhpryor@google.com
diff --git a/automotive/occupant_awareness/aidl/default/Android.bp b/automotive/occupant_awareness/aidl/default/Android.bp
index 4db43bb..66af9de 100644
--- a/automotive/occupant_awareness/aidl/default/Android.bp
+++ b/automotive/occupant_awareness/aidl/default/Android.bp
@@ -36,6 +36,6 @@
         "libbase",
         "libbinder_ndk",
         "libutils",
-        "android.hardware.automotive.occupant_awareness-V1-ndk_platform",
+        "android.hardware.automotive.occupant_awareness-V1-ndk",
     ],
 }
diff --git a/automotive/occupant_awareness/aidl/mock/Android.bp b/automotive/occupant_awareness/aidl/mock/Android.bp
index 275eb22..b804622 100644
--- a/automotive/occupant_awareness/aidl/mock/Android.bp
+++ b/automotive/occupant_awareness/aidl/mock/Android.bp
@@ -36,6 +36,6 @@
         "libbase",
         "libbinder_ndk",
         "libutils",
-        "android.hardware.automotive.occupant_awareness-V1-ndk_platform",
+        "android.hardware.automotive.occupant_awareness-V1-ndk",
     ],
 }
diff --git a/automotive/sv/1.0/default/Android.bp b/automotive/sv/1.0/default/Android.bp
index da974a0..82e11a8 100644
--- a/automotive/sv/1.0/default/Android.bp
+++ b/automotive/sv/1.0/default/Android.bp
@@ -29,9 +29,7 @@
     relative_install_path: "hw",
     srcs: [
         "service.cpp",
-        "SurroundViewService.cpp",
-        "SurroundView2dSession.cpp",
-        "SurroundView3dSession.cpp",
+        ":automotiveSvV1.0_sources",
     ],
     init_rc: ["android.hardware.automotive.sv@1.0-service.rc"],
     vintf_fragments: ["android.hardware.automotive.sv@1.0-service.xml"],
@@ -54,3 +52,17 @@
         "-g",
     ],
 }
+
+filegroup {
+    name: "automotiveSvV1.0_sources",
+    srcs: [
+        "SurroundViewService.cpp",
+        "SurroundView2dSession.cpp",
+        "SurroundView3dSession.cpp",
+    ],
+}
+
+cc_library_headers {
+    name: "automotiveSvV1.0_headers",
+    export_include_dirs: ["."],
+}
diff --git a/automotive/sv/1.0/default/tests/fuzzer/Android.bp b/automotive/sv/1.0/default/tests/fuzzer/Android.bp
new file mode 100644
index 0000000..394c532
--- /dev/null
+++ b/automotive/sv/1.0/default/tests/fuzzer/Android.bp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_fuzz {
+    name: "automotiveSvV1.0_fuzzer",
+    srcs: [
+        "AutomotiveSvV1_0Fuzzer.cpp",
+        "SurroundViewStream.cpp",
+        ":automotiveSvV1.0_sources",
+    ],
+    header_libs: [
+        "automotiveSvV1.0_headers",
+    ],
+    shared_libs: [
+        "android.hardware.automotive.sv@1.0",
+        "android.hidl.allocator@1.0",
+        "libhidlbase",
+        "libutils",
+        "libhidlmemory",
+        "liblog",
+    ],
+    fuzz_config: {
+        cc: [
+            "android-media-fuzzing-reports@google.com",
+        ],
+        componentid: 533764,
+    },
+}
diff --git a/automotive/sv/1.0/default/tests/fuzzer/AutomotiveSvV1_0Fuzzer.cpp b/automotive/sv/1.0/default/tests/fuzzer/AutomotiveSvV1_0Fuzzer.cpp
new file mode 100644
index 0000000..98834f5
--- /dev/null
+++ b/automotive/sv/1.0/default/tests/fuzzer/AutomotiveSvV1_0Fuzzer.cpp
@@ -0,0 +1,433 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "AutomotiveSvV1_0Fuzzer.h"
+#include <SurroundViewStream.h>
+#include <android/hidl/allocator/1.0/IAllocator.h>
+#include <hidlmemory/mapping.h>
+
+namespace android::hardware::automotive::sv::V1_0::implementation::fuzzer {
+
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hidl::allocator::V1_0::IAllocator;
+
+constexpr uint32_t kMinConfigDimension = 0;
+constexpr uint32_t kMaxConfigDimension = 4096;
+constexpr uint32_t kVertexByteSize = (3 * sizeof(float)) + 4;
+constexpr uint32_t kIdByteSize = 2;
+constexpr size_t kMaxCharacters = 30;
+constexpr size_t kMaxVertices = 10;
+constexpr size_t kMaxCameraPoints = 10;
+constexpr size_t kMaxViews = 10;
+constexpr size_t kMaxOverlays = 10;
+constexpr size_t kMinSvBuffers = 0;
+constexpr size_t kMaxSvBuffers = 10;
+
+void SurroundViewFuzzer::invoke2dSessionAPI() {
+    sp<ISurroundView2dSession> surroundView2dSession;
+
+    while (mFuzzedDataProvider.remaining_bytes() > 0) {
+        auto surroundView2dFunc = mFuzzedDataProvider.PickValueInArray<
+                const std::function<void()>>({
+                [&]() {
+                    mSurroundViewService->start2dSession(
+                            [&surroundView2dSession](const sp<ISurroundView2dSession>& session,
+                                                     SvResult result) {
+                                if (result == SvResult::OK) {
+                                    surroundView2dSession = session;
+                                }
+                            });
+                },
+                [&]() {
+                    if (surroundView2dSession) {
+                        sp<SurroundViewStream> handler =
+                                sp<SurroundViewStream>::make(surroundView2dSession);
+                        surroundView2dSession->startStream(handler);
+                        mIs2dStreamStarted = true;
+                    }
+                },
+                [&]() {
+                    if (surroundView2dSession) {
+                        surroundView2dSession->get2dMappingInfo(
+                                []([[maybe_unused]] Sv2dMappingInfo info) {});
+                    }
+                },
+                [&]() {
+                    if (surroundView2dSession) {
+                        Sv2dConfig config;
+                        config.width = mFuzzedDataProvider.ConsumeIntegralInRange<uint32_t>(
+                                kMinConfigDimension, kMaxConfigDimension);
+                        if (mFuzzedDataProvider.ConsumeBool()) {
+                            config.blending = static_cast<SvQuality>(
+                                    mFuzzedDataProvider.ConsumeIntegral<uint32_t>());
+                        } else {
+                            config.blending = mFuzzedDataProvider.ConsumeBool() ? (SvQuality::HIGH)
+                                                                                : (SvQuality::LOW);
+                        }
+                        surroundView2dSession->set2dConfig(config);
+                    }
+                },
+                [&]() {
+                    if (surroundView2dSession) {
+                        surroundView2dSession->get2dConfig([&](Sv2dConfig) {});
+                    }
+                },
+                [&]() {
+                    if (surroundView2dSession) {
+                        hidl_vec<Point2dInt> points2dCamera;
+                        const size_t camPoints = mFuzzedDataProvider.ConsumeIntegralInRange<size_t>(
+                                1, kMaxCameraPoints);
+                        points2dCamera.resize(camPoints);
+                        for (size_t i = 0; i < camPoints; ++i) {
+                            points2dCamera[i].x = mFuzzedDataProvider.ConsumeFloatingPoint<float>();
+                            points2dCamera[i].y = mFuzzedDataProvider.ConsumeFloatingPoint<float>();
+                        }
+
+                        hidl_vec<hidl_string> cameraIds;
+                        mSurroundViewService->getCameraIds(
+                                [&cameraIds](const hidl_vec<hidl_string>& camIds) {
+                                    cameraIds = camIds;
+                                });
+                        hidl_string cameraId;
+                        if (cameraIds.size() > 0 && mFuzzedDataProvider.ConsumeBool()) {
+                            const size_t cameraIndex =
+                                    mFuzzedDataProvider.ConsumeIntegralInRange<size_t>(
+                                            0, cameraIds.size() - 1);
+                            cameraId = cameraIds[cameraIndex];
+                        } else {
+                            cameraId =
+                                    mFuzzedDataProvider.ConsumeRandomLengthString(kMaxCharacters);
+                        }
+                        surroundView2dSession->projectCameraPoints(
+                                points2dCamera, cameraId,
+                                []([[maybe_unused]] const hidl_vec<Point2dFloat>& outPoints) {});
+                    }
+                },
+                [&]() {
+                    if (surroundView2dSession) {
+                        SvFramesDesc frames;
+                        frames.timestampNs = mFuzzedDataProvider.ConsumeIntegral<uint64_t>();
+                        frames.sequenceId = mFuzzedDataProvider.ConsumeIntegral<uint32_t>();
+                        size_t numSvBuffers = mFuzzedDataProvider.ConsumeIntegralInRange<size_t>(
+                                kMinSvBuffers, kMaxSvBuffers);
+                        frames.svBuffers.resize(numSvBuffers);
+                        for (int i = 0; i < numSvBuffers; ++i) {
+                            frames.svBuffers[i].viewId =
+                                    mFuzzedDataProvider.ConsumeIntegral<uint32_t>();
+                            frames.svBuffers[i].hardwareBuffer.nativeHandle = new native_handle_t();
+                            frames.svBuffers[i].hardwareBuffer.description[0] =
+                                    mFuzzedDataProvider.ConsumeIntegral<uint32_t>();
+                            frames.svBuffers[i].hardwareBuffer.description[1] =
+                                    mFuzzedDataProvider.ConsumeIntegral<uint32_t>();
+                        }
+                        surroundView2dSession->doneWithFrames(frames);
+                        for (int i = 0; i < numSvBuffers; ++i) {
+                            delete frames.svBuffers[i].hardwareBuffer.nativeHandle;
+                        }
+                    }
+                },
+                [&]() {
+                    if (surroundView2dSession) {
+                        surroundView2dSession->stopStream();
+                        mIs2dStreamStarted = false;
+                    }
+                },
+                [&]() {
+                    mSurroundViewService->stop2dSession(
+                            mFuzzedDataProvider.ConsumeBool() ? surroundView2dSession : nullptr);
+                },
+        });
+        surroundView2dFunc();
+    }
+
+    if (surroundView2dSession && mIs2dStreamStarted) {
+        surroundView2dSession->stopStream();
+    }
+}
+
+void SurroundViewFuzzer::invoke3dSessionAPI() {
+    sp<ISurroundView3dSession> surroundView3dSession;
+    while (mFuzzedDataProvider.remaining_bytes() > 0) {
+        auto surroundView3dFunc = mFuzzedDataProvider.PickValueInArray<
+                const std::function<void()>>({
+                [&]() {
+                    mSurroundViewService->start3dSession(
+                            [&surroundView3dSession](const sp<ISurroundView3dSession>& session,
+                                                     SvResult result) {
+                                if (result == SvResult::OK) {
+                                    surroundView3dSession = session;
+                                }
+                            });
+                },
+                [&]() {
+                    if (surroundView3dSession) {
+                        sp<SurroundViewStream> handler =
+                                sp<SurroundViewStream>::make(surroundView3dSession);
+                        surroundView3dSession->startStream(handler);
+                        mIs3dStreamStarted = true;
+                    }
+                },
+                [&]() {
+                    if (surroundView3dSession) {
+                        const size_t numViews =
+                                mFuzzedDataProvider.ConsumeIntegralInRange<size_t>(1, kMaxViews);
+                        std::vector<View3d> views(numViews);
+                        for (size_t i = 0; i < numViews; ++i) {
+                            views[i].viewId = mFuzzedDataProvider.ConsumeIntegral<uint32_t>();
+                        }
+                        surroundView3dSession->setViews(views);
+                    }
+                },
+                [&]() {
+                    if (surroundView3dSession) {
+                        Sv3dConfig config;
+                        config.width = mFuzzedDataProvider.ConsumeIntegralInRange<uint32_t>(
+                                kMinConfigDimension, kMaxConfigDimension);
+                        config.height = mFuzzedDataProvider.ConsumeIntegralInRange<uint32_t>(
+                                kMinConfigDimension, kMaxConfigDimension);
+                        if (mFuzzedDataProvider.ConsumeBool()) {
+                            config.carDetails = static_cast<SvQuality>(
+                                    mFuzzedDataProvider.ConsumeIntegral<uint32_t>());
+                        } else {
+                            config.carDetails = mFuzzedDataProvider.ConsumeBool()
+                                                        ? (SvQuality::HIGH)
+                                                        : (SvQuality::LOW);
+                        }
+                        surroundView3dSession->set3dConfig(config);
+                    }
+                },
+                [&]() {
+                    if (surroundView3dSession) {
+                        surroundView3dSession->get3dConfig([&](Sv3dConfig) {});
+                    }
+                },
+                [&]() {
+                    if (surroundView3dSession) {
+                        Point2dInt cameraPoint;
+                        cameraPoint.x = mFuzzedDataProvider.ConsumeFloatingPoint<float>();
+                        cameraPoint.y = mFuzzedDataProvider.ConsumeFloatingPoint<float>();
+                        std::vector<Point2dInt> cameraPoints = {cameraPoint};
+                        hidl_vec<hidl_string> cameraIds;
+                        mSurroundViewService->getCameraIds(
+                                [&cameraIds](const hidl_vec<hidl_string>& camIds) {
+                                    cameraIds = camIds;
+                                });
+                        hidl_string cameraId;
+                        if (cameraIds.size() > 0 && mFuzzedDataProvider.ConsumeBool()) {
+                            const size_t cameraIndex =
+                                    mFuzzedDataProvider.ConsumeIntegralInRange<size_t>(
+                                            0, cameraIds.size() - 1);
+                            cameraId = cameraIds[cameraIndex];
+                        } else {
+                            cameraId =
+                                    mFuzzedDataProvider.ConsumeRandomLengthString(kMaxCharacters);
+                        }
+                        std::vector<Point3dFloat> points3d;
+                        surroundView3dSession->projectCameraPointsTo3dSurface(
+                                cameraPoints, cameraId,
+                                [&points3d]([[maybe_unused]] const hidl_vec<Point3dFloat>&
+                                                    points3dproj) { points3d = points3dproj; });
+                    }
+                },
+                [&]() {
+                    if (surroundView3dSession) {
+                        // success case
+                        surroundView3dSession->updateOverlays(mOverlaysdata);
+                    }
+                },
+                [&]() {
+                    if (surroundView3dSession) {
+                        initSampleOverlaysData();
+                        // Fail with ID mismatch
+                        // Set id of second overlay in shared memory to 2 (expected is 1).
+                        auto& overlaysDescVector = mOverlaysdata.overlaysMemoryDesc;
+                        auto& pIMemory = mMemory;
+                        int32_t indexPosition = mFuzzedDataProvider.ConsumeIntegralInRange<int32_t>(
+                                0, mNumOverlays - 1);
+                        int32_t mismatchedValueIndex =
+                                mFuzzedDataProvider.ConsumeIntegralInRange<int32_t>(
+                                        0, mNumOverlays - 1);
+                        setIndexOfOverlaysMemory(overlaysDescVector, pIMemory, indexPosition,
+                                                 overlaysDescVector[mismatchedValueIndex].id);
+                        surroundView3dSession->updateOverlays(mOverlaysdata);
+                    }
+                },
+                [&]() {
+                    if (surroundView3dSession) {
+                        // Fail with NULL memory
+                        // Set shared memory to null.
+                        mOverlaysdata.overlaysMemory = hidl_memory();
+                        surroundView3dSession->updateOverlays(mOverlaysdata);
+                    }
+                },
+                [&]() {
+                    if (surroundView3dSession) {
+                        SvFramesDesc frames;
+                        frames.timestampNs = mFuzzedDataProvider.ConsumeIntegral<uint64_t>();
+                        frames.sequenceId = mFuzzedDataProvider.ConsumeIntegral<uint32_t>();
+                        size_t numSvBuffers = mFuzzedDataProvider.ConsumeIntegralInRange<size_t>(
+                                kMinSvBuffers, kMaxSvBuffers);
+                        frames.svBuffers.resize(numSvBuffers);
+                        for (int i = 0; i < numSvBuffers; ++i) {
+                            frames.svBuffers[i].viewId =
+                                    mFuzzedDataProvider.ConsumeIntegral<uint32_t>();
+                            frames.svBuffers[i].hardwareBuffer.nativeHandle = new native_handle_t();
+                            frames.svBuffers[i].hardwareBuffer.description[0] =
+                                    mFuzzedDataProvider.ConsumeIntegral<uint32_t>();
+                            frames.svBuffers[i].hardwareBuffer.description[1] =
+                                    mFuzzedDataProvider.ConsumeIntegral<uint32_t>();
+                        }
+                        surroundView3dSession->doneWithFrames(frames);
+                        for (int i = 0; i < numSvBuffers; ++i) {
+                            delete frames.svBuffers[i].hardwareBuffer.nativeHandle;
+                        }
+                    }
+                },
+                [&]() {
+                    if (surroundView3dSession) {
+                        surroundView3dSession->stopStream();
+                        mIs3dStreamStarted = false;
+                    }
+                },
+                [&]() {
+                    mSurroundViewService->stop3dSession(
+                            mFuzzedDataProvider.ConsumeBool() ? surroundView3dSession : nullptr);
+                },
+        });
+        surroundView3dFunc();
+    }
+    if (surroundView3dSession && mIs3dStreamStarted) {
+        surroundView3dSession->stopStream();
+    }
+}
+
+void SurroundViewFuzzer::process() {
+    mFuzzedDataProvider.ConsumeBool() ? invoke2dSessionAPI() : invoke3dSessionAPI();
+}
+
+std::pair<hidl_memory, sp<IMemory>> SurroundViewFuzzer::getMappedSharedMemory(int32_t bytesSize) {
+    const auto nullResult = std::make_pair(hidl_memory(), nullptr);
+
+    sp<IAllocator> ashmemAllocator = IAllocator::getService("ashmem");
+    if (ashmemAllocator.get() == nullptr) {
+        return nullResult;
+    }
+
+    // Allocate shared memory.
+    hidl_memory hidlMemory;
+    bool allocateSuccess = false;
+    Return<void> result =
+            ashmemAllocator->allocate(bytesSize, [&](bool success, const hidl_memory& hidlMem) {
+                if (!success) {
+                    return;
+                }
+                allocateSuccess = success;
+                hidlMemory = hidlMem;
+            });
+
+    // Check result of allocated memory.
+    if (!result.isOk() || !allocateSuccess) {
+        return nullResult;
+    }
+
+    // Map shared memory.
+    sp<IMemory> pIMemory = mapMemory(hidlMemory);
+    if (pIMemory.get() == nullptr) {
+        return nullResult;
+    }
+
+    return std::make_pair(hidlMemory, pIMemory);
+}
+
+void SurroundViewFuzzer::setIndexOfOverlaysMemory(
+        const std::vector<OverlayMemoryDesc>& overlaysMemDesc, sp<IMemory> pIMemory,
+        int32_t indexPosition, uint16_t indexValue) {
+    // Count the number of vertices until the index.
+    int32_t totalVerticesCount = 0;
+    for (int32_t i = 0; i < indexPosition; ++i) {
+        totalVerticesCount += overlaysMemDesc[i].verticesCount;
+    }
+
+    const int32_t indexBytePosition =
+            (indexPosition * kIdByteSize) + (kVertexByteSize * totalVerticesCount);
+
+    uint8_t* pSharedMemoryData = (uint8_t*)((void*)pIMemory->getPointer());
+    pSharedMemoryData += indexBytePosition;
+    uint16_t* pIndex16bit = (uint16_t*)pSharedMemoryData;
+
+    // Modify shared memory.
+    pIMemory->update();
+    *pIndex16bit = indexValue;
+    pIMemory->commit();
+}
+
+void SurroundViewFuzzer::initSampleOverlaysData() {
+    const size_t mNumOverlays =
+            mFuzzedDataProvider.ConsumeIntegralInRange<size_t>(kMinOverlays, kMaxOverlays);
+    mOverlaysdata.overlaysMemoryDesc.resize(mNumOverlays);
+
+    int32_t sharedMemBytesSize = 0;
+    std::vector<OverlayMemoryDesc> overlaysDescVector = {};
+    OverlayMemoryDesc overlayMemDesc[mNumOverlays];
+    for (size_t i = 0; i < mNumOverlays; ++i) {
+        overlayMemDesc[i].id = i;
+        overlayMemDesc[i].verticesCount =
+                mFuzzedDataProvider.ConsumeIntegralInRange<size_t>(1, kMaxVertices);
+        overlayMemDesc[i].overlayPrimitive = mFuzzedDataProvider.ConsumeBool()
+                                                     ? (OverlayPrimitive::TRIANGLES)
+                                                     : (OverlayPrimitive::TRIANGLES_STRIP);
+        mOverlaysdata.overlaysMemoryDesc[i] = overlayMemDesc[i];
+
+        sharedMemBytesSize += kIdByteSize + kVertexByteSize * overlayMemDesc[i].verticesCount;
+        overlaysDescVector.push_back(overlayMemDesc[i]);
+    }
+
+    std::pair<hidl_memory, sp<IMemory>> sharedMem = getMappedSharedMemory(sharedMemBytesSize);
+    sp<IMemory> pIMemory = std::get<1>(sharedMem);
+    if (pIMemory.get() == nullptr) {
+        mOverlaysdata = OverlaysData();
+        mMemory = nullptr;
+        return;
+    }
+
+    // Get pointer to shared memory data and set all bytes to 0.
+    uint8_t* pSharedMemoryData = (uint8_t*)((void*)pIMemory->getPointer());
+    pIMemory->update();
+    memset(pSharedMemoryData, 0, sharedMemBytesSize);
+    pIMemory->commit();
+
+    // Set indexes in shared memory.
+    for (size_t i = 0; i < mNumOverlays; ++i) {
+        setIndexOfOverlaysMemory(overlaysDescVector, pIMemory, i, overlayMemDesc[i].id);
+    }
+
+    mOverlaysdata.overlaysMemoryDesc = overlaysDescVector;
+    mOverlaysdata.overlaysMemory = std::get<0>(sharedMem);
+    mMemory = pIMemory;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    if (size < 1) {
+        return 0;
+    }
+    SurroundViewFuzzer surroundViewFuzzer(data, size);
+    surroundViewFuzzer.process();
+    return 0;
+}
+}  // namespace android::hardware::automotive::sv::V1_0::implementation::fuzzer
diff --git a/automotive/sv/1.0/default/tests/fuzzer/AutomotiveSvV1_0Fuzzer.h b/automotive/sv/1.0/default/tests/fuzzer/AutomotiveSvV1_0Fuzzer.h
new file mode 100644
index 0000000..23e5a31
--- /dev/null
+++ b/automotive/sv/1.0/default/tests/fuzzer/AutomotiveSvV1_0Fuzzer.h
@@ -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.
+ *
+ */
+#pragma once
+#include <SurroundViewService.h>
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+namespace android::hardware::automotive::sv::V1_0::implementation::fuzzer {
+
+using ::android::sp;
+using ::android::hidl::memory::V1_0::IMemory;
+
+constexpr size_t kMinOverlays = 2;
+
+class SurroundViewFuzzer {
+  public:
+    SurroundViewFuzzer(const uint8_t* data, size_t size) : mFuzzedDataProvider(data, size) {
+        mSurroundViewService = sp<SurroundViewService>::make();
+    }
+    ~SurroundViewFuzzer() = default;
+    void process();
+
+  private:
+    void invoke2dSessionAPI();
+    void invoke3dSessionAPI();
+    std::pair<hidl_memory, sp<IMemory>> getMappedSharedMemory(int32_t bytesSize);
+    void initSampleOverlaysData();
+    void setIndexOfOverlaysMemory(const std::vector<OverlayMemoryDesc>& overlaysMemDesc,
+                                  sp<IMemory> pIMemory, int32_t indexPosition, uint16_t indexValue);
+    OverlaysData mOverlaysdata = {};
+    size_t mNumOverlays = kMinOverlays;
+    sp<IMemory> mMemory = nullptr;
+    FuzzedDataProvider mFuzzedDataProvider;
+    sp<SurroundViewService> mSurroundViewService = nullptr;
+    bool mIs2dStreamStarted = false;
+    bool mIs3dStreamStarted = false;
+};
+}  // namespace android::hardware::automotive::sv::V1_0::implementation::fuzzer
diff --git a/automotive/sv/1.0/default/tests/fuzzer/SurroundViewStream.cpp b/automotive/sv/1.0/default/tests/fuzzer/SurroundViewStream.cpp
new file mode 100644
index 0000000..b81a08c
--- /dev/null
+++ b/automotive/sv/1.0/default/tests/fuzzer/SurroundViewStream.cpp
@@ -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.
+ */
+
+#include "SurroundViewStream.h"
+
+namespace android::hardware::automotive::sv::V1_0::implementation::fuzzer {
+
+using std::lock_guard;
+
+SurroundViewStream::SurroundViewStream(sp<ISurroundViewSession> pSession)
+    : mSession(pSession), mReceiveFramesCount(0) {}
+
+Return<void> SurroundViewStream::notify(SvEvent svEvent) {
+    lock_guard<mutex> lock(mLock);
+    switch (svEvent) {
+        case SvEvent::STREAM_STARTED:
+        case SvEvent::CONFIG_UPDATED:
+        case SvEvent::STREAM_STOPPED:
+        case SvEvent::FRAME_DROPPED:
+        case SvEvent::TIMEOUT:
+            mReceivedEvents.emplace_back(svEvent);
+            break;
+        default:
+            break;
+    }
+
+    return android::hardware::Void();
+}
+
+Return<void> SurroundViewStream::receiveFrames(const SvFramesDesc& svFramesDesc) {
+    lock_guard<mutex> lock(mLock);
+    if ((mLastReceivedFrames.timestampNs >= svFramesDesc.timestampNs ||
+         mLastReceivedFrames.sequenceId >= svFramesDesc.sequenceId) &&
+        mReceiveFramesCount != 0) {
+        // The incoming frames are with invalid timestamp or sequenceId
+        mAllFramesValid = false;
+    }
+
+    for (int i = 0; i < svFramesDesc.svBuffers.size(); ++i) {
+        if (svFramesDesc.svBuffers[i].hardwareBuffer.nativeHandle == nullptr) {
+            mAllFramesValid = false;
+            // The incoming frames are with invalid nativeHandle
+            break;
+        }
+    }
+
+    ++mReceiveFramesCount;
+
+    // Store all the information except for the handle
+    mLastReceivedFrames.timestampNs = svFramesDesc.timestampNs;
+    mLastReceivedFrames.sequenceId = svFramesDesc.sequenceId;
+    mLastReceivedFrames.svBuffers.resize(svFramesDesc.svBuffers.size());
+    for (int i = 0; i < svFramesDesc.svBuffers.size(); ++i) {
+        mLastReceivedFrames.svBuffers[i].viewId = svFramesDesc.svBuffers[i].viewId;
+        mLastReceivedFrames.svBuffers[i].hardwareBuffer.description =
+                svFramesDesc.svBuffers[i].hardwareBuffer.description;
+    }
+
+    return android::hardware::Void();
+}
+}  // namespace android::hardware::automotive::sv::V1_0::implementation::fuzzer
diff --git a/automotive/sv/1.0/default/tests/fuzzer/SurroundViewStream.h b/automotive/sv/1.0/default/tests/fuzzer/SurroundViewStream.h
new file mode 100644
index 0000000..8135bc1
--- /dev/null
+++ b/automotive/sv/1.0/default/tests/fuzzer/SurroundViewStream.h
@@ -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.
+ */
+
+#pragma once
+
+#include <android/hardware/automotive/sv/1.0/ISurroundViewSession.h>
+#include <android/hardware/automotive/sv/1.0/ISurroundViewStream.h>
+#include <android/hardware/automotive/sv/1.0/types.h>
+
+#include <thread>
+#include <vector>
+
+namespace android::hardware::automotive::sv::V1_0::implementation::fuzzer {
+
+using android::sp;
+using android::hardware::Return;
+using std::mutex;
+using std::vector;
+
+class SurroundViewStream : public ISurroundViewStream {
+  public:
+    SurroundViewStream(sp<ISurroundViewSession> session);
+
+    Return<void> notify(SvEvent svEvent) override;
+    Return<void> receiveFrames(const SvFramesDesc& svFramesDesc) override;
+
+    bool checkEventReceived(SvEvent svEvent);
+    SvFramesDesc getLastReceivedFrames();
+    int getReceiveFramesCount();
+    bool areAllFramesValid();
+    void setDoNotReturnFrames(bool flag);
+
+  private:
+    mutex mLock;
+
+    vector<SvEvent> mReceivedEvents;
+    sp<ISurroundViewSession> mSession;
+    SvFramesDesc mLastReceivedFrames;
+    int mReceiveFramesCount;
+    bool mAllFramesValid = true;
+};
+}  // namespace android::hardware::automotive::sv::V1_0::implementation::fuzzer
diff --git a/automotive/sv/1.0/vts/functional/Android.bp b/automotive/sv/1.0/vts/functional/Android.bp
index 1ff3450..e94893c 100644
--- a/automotive/sv/1.0/vts/functional/Android.bp
+++ b/automotive/sv/1.0/vts/functional/Android.bp
@@ -25,6 +25,9 @@
 
 cc_test {
     name: "VtsHalSurroundViewV1_0TargetTest",
+    tidy_timeout_srcs: [
+        "VtsHalSurroundViewV1_0TargetTest.cpp",
+    ],
     srcs: [
         "VtsHalSurroundViewV1_0TargetTest.cpp",
         "SurroundViewStreamHandler.cpp",
diff --git a/automotive/sv/1.0/vts/functional/OWNERS b/automotive/sv/1.0/vts/functional/OWNERS
new file mode 100644
index 0000000..2ba00a3
--- /dev/null
+++ b/automotive/sv/1.0/vts/functional/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 821659
+tanmayp@google.com
+ankitarora@google.com
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp
index 0b49ef9..ba33098 100644
--- a/automotive/vehicle/2.0/default/Android.bp
+++ b/automotive/vehicle/2.0/default/Android.bp
@@ -41,7 +41,7 @@
     defaults: ["vhal_v2_0_defaults"],
     shared_libs: [
         "libbinder_ndk",
-        "android.automotive.watchdog-V2-ndk_platform",
+        "android.automotive.watchdog-V2-ndk",
     ],
 }
 
@@ -172,6 +172,9 @@
     vendor: true,
     defaults: ["vhal_v2_0_target_defaults"],
     whole_static_libs: ["android.hardware.automotive.vehicle@2.0-manager-lib"],
+    tidy_timeout_srcs: [
+        "tests/VmsUtils_test.cpp",
+    ],
     srcs: [
         "tests/RecurrentTimer_test.cpp",
         "tests/SubscriptionManager_test.cpp",
diff --git a/automotive/vehicle/2.0/utils/Android.bp b/automotive/vehicle/2.0/utils/Android.bp
index a75ce49..770d447 100644
--- a/automotive/vehicle/2.0/utils/Android.bp
+++ b/automotive/vehicle/2.0/utils/Android.bp
@@ -39,6 +39,9 @@
     name: "android.hardware.automotive.vehicle@2.0-utils-unit-tests",
     defaults: ["vhal_v2_0_defaults"],
     vendor: true,
+    tidy_timeout_srcs: [
+        "tests/UserHalHelper_test.cpp",
+    ],
     srcs: [
         "tests/UserHalHelper_test.cpp",
     ],
diff --git a/automotive/vehicle/2.0/vts/functional/OWNERS b/automotive/vehicle/2.0/vts/functional/OWNERS
new file mode 100644
index 0000000..8a0f2af
--- /dev/null
+++ b/automotive/vehicle/2.0/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 533426
+kwangsudo@google.com
diff --git a/automotive/vehicle/OWNERS b/automotive/vehicle/OWNERS
new file mode 100644
index 0000000..429ec39
--- /dev/null
+++ b/automotive/vehicle/OWNERS
@@ -0,0 +1,3 @@
+ericjeong@google.com
+keunyoung@google.com
+shanyu@google.com
diff --git a/biometrics/face/1.0/default/android.hardware.biometrics.face@1.0-service.rc b/biometrics/face/1.0/default/android.hardware.biometrics.face@1.0-service.rc
index 6c7362f..3fb827d 100644
--- a/biometrics/face/1.0/default/android.hardware.biometrics.face@1.0-service.rc
+++ b/biometrics/face/1.0/default/android.hardware.biometrics.face@1.0-service.rc
@@ -5,6 +5,6 @@
     class late_start
     user system
     group system
-    writepid /dev/cpuset/foreground/tasks
+    task_profiles ProcessCapacityHigh
     capabilities SYS_NICE
     rlimit rtprio 10 10
diff --git a/biometrics/face/1.0/vts/functional/OWNERS b/biometrics/face/1.0/vts/functional/OWNERS
new file mode 100644
index 0000000..7651b69
--- /dev/null
+++ b/biometrics/face/1.0/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 432605
+ilyamaty@google.com
diff --git a/biometrics/face/aidl/default/Android.bp b/biometrics/face/aidl/default/Android.bp
index d72411e..5092318 100644
--- a/biometrics/face/aidl/default/Android.bp
+++ b/biometrics/face/aidl/default/Android.bp
@@ -16,8 +16,8 @@
     shared_libs: [
         "libbase",
         "libbinder_ndk",
-        "android.hardware.biometrics.face-V1-ndk_platform",
-        "android.hardware.biometrics.common-V1-ndk_platform",
+        "android.hardware.biometrics.face-V1-ndk",
+        "android.hardware.biometrics.common-V1-ndk",
     ],
     srcs: [
         "main.cpp",
diff --git a/biometrics/face/aidl/default/main.cpp b/biometrics/face/aidl/default/main.cpp
index 80b153e..b7274e3 100644
--- a/biometrics/face/aidl/default/main.cpp
+++ b/biometrics/face/aidl/default/main.cpp
@@ -29,7 +29,7 @@
 
     const std::string instance = std::string(Face::descriptor) + "/default";
     binder_status_t status = AServiceManager_addService(hal->asBinder().get(), instance.c_str());
-    CHECK(status == STATUS_OK);
+    CHECK_EQ(status, STATUS_OK);
 
     ABinderProcess_joinThreadPool();
     return EXIT_FAILURE;  // should not reach
diff --git a/biometrics/face/aidl/vts/Android.bp b/biometrics/face/aidl/vts/Android.bp
index 99c8c99..09ec4d0 100644
--- a/biometrics/face/aidl/vts/Android.bp
+++ b/biometrics/face/aidl/vts/Android.bp
@@ -15,10 +15,10 @@
     ],
     srcs: ["VtsHalBiometricsFaceTargetTest.cpp"],
     static_libs: [
-        "android.hardware.biometrics.common-V1-ndk_platform",
-        "android.hardware.biometrics.face-V1-ndk_platform",
-        "android.hardware.common-V2-ndk_platform",
-        "android.hardware.keymaster-V3-ndk_platform",
+        "android.hardware.biometrics.common-V1-ndk",
+        "android.hardware.biometrics.face-V1-ndk",
+        "android.hardware.common-V2-ndk",
+        "android.hardware.keymaster-V3-ndk",
     ],
     shared_libs: [
         "libbinder_ndk",
diff --git a/biometrics/fingerprint/2.1/default/android.hardware.biometrics.fingerprint@2.1-service.rc b/biometrics/fingerprint/2.1/default/android.hardware.biometrics.fingerprint@2.1-service.rc
index 1667677..e7e8d30 100644
--- a/biometrics/fingerprint/2.1/default/android.hardware.biometrics.fingerprint@2.1-service.rc
+++ b/biometrics/fingerprint/2.1/default/android.hardware.biometrics.fingerprint@2.1-service.rc
@@ -5,4 +5,4 @@
     class late_start
     user system
     group system input uhid
-    writepid /dev/cpuset/system-background/tasks
+    task_profiles ServiceCapacityLow
diff --git a/biometrics/fingerprint/2.1/vts/functional/Android.bp b/biometrics/fingerprint/2.1/vts/functional/Android.bp
index 0935bf6..68b3360 100644
--- a/biometrics/fingerprint/2.1/vts/functional/Android.bp
+++ b/biometrics/fingerprint/2.1/vts/functional/Android.bp
@@ -26,6 +26,7 @@
 cc_test {
     name: "VtsHalBiometricsFingerprintV2_1TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: ["VtsHalBiometricsFingerprintV2_1TargetTest.cpp"],
     srcs: ["VtsHalBiometricsFingerprintV2_1TargetTest.cpp"],
     static_libs: ["android.hardware.biometrics.fingerprint@2.1"],
     test_suites: ["general-tests", "vts"],
diff --git a/biometrics/fingerprint/2.1/vts/functional/OWNERS b/biometrics/fingerprint/2.1/vts/functional/OWNERS
new file mode 100644
index 0000000..0014ce9
--- /dev/null
+++ b/biometrics/fingerprint/2.1/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 114777
+ilyamaty@google.com
diff --git a/biometrics/fingerprint/2.2/vts/functional/OWNERS b/biometrics/fingerprint/2.2/vts/functional/OWNERS
new file mode 100644
index 0000000..0014ce9
--- /dev/null
+++ b/biometrics/fingerprint/2.2/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 114777
+ilyamaty@google.com
diff --git a/biometrics/fingerprint/aidl/default/Android.bp b/biometrics/fingerprint/aidl/default/Android.bp
index 80e6e02..08fe4b0 100644
--- a/biometrics/fingerprint/aidl/default/Android.bp
+++ b/biometrics/fingerprint/aidl/default/Android.bp
@@ -24,8 +24,8 @@
     shared_libs: [
         "libbase",
         "libbinder_ndk",
-        "android.hardware.biometrics.fingerprint-V1-ndk_platform",
-        "android.hardware.biometrics.common-V1-ndk_platform",
+        "android.hardware.biometrics.fingerprint-V1-ndk",
+        "android.hardware.biometrics.common-V1-ndk",
     ],
 }
 
diff --git a/biometrics/fingerprint/aidl/default/main.cpp b/biometrics/fingerprint/aidl/default/main.cpp
index 4690d73..c985201 100644
--- a/biometrics/fingerprint/aidl/default/main.cpp
+++ b/biometrics/fingerprint/aidl/default/main.cpp
@@ -29,7 +29,7 @@
 
     const std::string instance = std::string(Fingerprint::descriptor) + "/default";
     binder_status_t status = AServiceManager_addService(hal->asBinder().get(), instance.c_str());
-    CHECK(status == STATUS_OK);
+    CHECK_EQ(status, STATUS_OK);
 
     ABinderProcess_joinThreadPool();
     return EXIT_FAILURE;  // should not reach
diff --git a/biometrics/fingerprint/aidl/vts/Android.bp b/biometrics/fingerprint/aidl/vts/Android.bp
index 5539548..30d5624 100644
--- a/biometrics/fingerprint/aidl/vts/Android.bp
+++ b/biometrics/fingerprint/aidl/vts/Android.bp
@@ -15,9 +15,9 @@
     ],
     srcs: ["VtsHalBiometricsFingerprintTargetTest.cpp"],
     static_libs: [
-        "android.hardware.biometrics.common-V1-ndk_platform",
-        "android.hardware.biometrics.fingerprint-V1-ndk_platform",
-        "android.hardware.keymaster-V3-ndk_platform",
+        "android.hardware.biometrics.common-V1-ndk",
+        "android.hardware.biometrics.fingerprint-V1-ndk",
+        "android.hardware.keymaster-V3-ndk",
     ],
     shared_libs: [
         "libbinder_ndk",
diff --git a/bluetooth/1.0/default/Android.bp b/bluetooth/1.0/default/Android.bp
index 70a42b7..84a49cf 100644
--- a/bluetooth/1.0/default/Android.bp
+++ b/bluetooth/1.0/default/Android.bp
@@ -22,9 +22,8 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
-cc_library_shared {
-    name: "android.hardware.bluetooth@1.0-impl",
-    defaults: ["hidl_defaults"],
+cc_defaults {
+    name: "android.hardware.bluetooth@1.0-defaults",
     vendor: true,
     relative_install_path: "hw",
     srcs: [
@@ -47,6 +46,25 @@
     ],
 }
 
+cc_library {
+    name: "android.hardware.bluetooth@1.0-impl",
+    defaults: [
+        "hidl_defaults",
+        "android.hardware.bluetooth@1.0-defaults",
+    ],
+}
+
+cc_library {
+    name: "android.hardware.bluetooth@1.0-impl-test",
+    defaults: [
+        "hidl_defaults",
+        "android.hardware.bluetooth@1.0-defaults",
+    ],
+    cflags: [
+        "-DBT_FUZZER",
+    ],
+}
+
 cc_library_static {
     name: "android.hardware.bluetooth-async",
     vendor: true,
diff --git a/bluetooth/1.0/default/h4_protocol.cc b/bluetooth/1.0/default/h4_protocol.cc
index 43abbe4..33238da 100644
--- a/bluetooth/1.0/default/h4_protocol.cc
+++ b/bluetooth/1.0/default/h4_protocol.cc
@@ -30,21 +30,52 @@
 namespace hci {
 
 size_t H4Protocol::Send(uint8_t type, const uint8_t* data, size_t length) {
-  struct iovec iov[] = {{&type, sizeof(type)},
-                        {const_cast<uint8_t*>(data), length}};
-  ssize_t ret = 0;
-  do {
-    ret =
-        TEMP_FAILURE_RETRY(writev(uart_fd_, iov, sizeof(iov) / sizeof(iov[0])));
-  } while (-1 == ret && EAGAIN == errno);
-
-  if (ret == -1) {
-    ALOGE("%s error writing to UART (%s)", __func__, strerror(errno));
-  } else if (ret < static_cast<ssize_t>(length + 1)) {
-    ALOGE("%s: %d / %d bytes written - something went wrong...", __func__,
-          static_cast<int>(ret), static_cast<int>(length + 1));
+  struct iovec iov_array[] = {{&type, sizeof(type)},
+                              {const_cast<uint8_t*>(data), length}};
+  struct iovec* iov = iov_array;
+  int iovcnt = sizeof(iov_array) / sizeof(iov_array[0]);
+  size_t total_bytes = 0;
+  for (int i = 0; i < iovcnt; i++) {
+    total_bytes += iov_array[i].iov_len;
   }
-  return ret;
+  size_t bytes_written = 0;
+  size_t remaining_bytes = total_bytes;
+
+  while (remaining_bytes > 0) {
+    ssize_t ret = TEMP_FAILURE_RETRY(writev(uart_fd_, iov, iovcnt));
+    if (ret == -1) {
+      if (errno == EAGAIN) continue;
+      ALOGE("%s error writing to UART (%s)", __func__, strerror(errno));
+      break;
+    } else if (ret == 0) {
+      // Nothing written
+      ALOGE("%s zero bytes written - something went wrong...", __func__);
+      break;
+    } else if (ret == remaining_bytes) {
+      // Everything written
+      bytes_written += ret;
+      break;
+    }
+
+    bytes_written += ret;
+    remaining_bytes -= ret;
+    ALOGW("%s: %d/%d bytes written - retrying remaining %d bytes", __func__,
+          static_cast<int>(bytes_written), static_cast<int>(total_bytes),
+          static_cast<int>(remaining_bytes));
+
+    // Remove iovs which are written from the list
+    while (ret >= iov->iov_len) {
+      ret -= iov->iov_len;
+      ++iov;
+      --iovcnt;
+    }
+    // Adjust the iov to point to the remaining data which needs to be written
+    if (ret) {
+      iov->iov_base = static_cast<uint8_t*>(iov->iov_base) + ret;
+      iov->iov_len -= ret;
+    }
+  }
+  return bytes_written;
 }
 
 void H4Protocol::OnPacketReady() {
diff --git a/bluetooth/1.0/default/test/fuzzer/Android.bp b/bluetooth/1.0/default/test/fuzzer/Android.bp
new file mode 100644
index 0000000..691136f
--- /dev/null
+++ b/bluetooth/1.0/default/test/fuzzer/Android.bp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+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: "libbt-vendor-fuzz",
+    vendor: true,
+    srcs: [
+        "bt_vendor.cpp",
+    ],
+    static_libs: [
+        "android.hardware.bluetooth@1.0-impl-test",
+        "android.hardware.bluetooth-hci",
+    ],
+}
+
+cc_fuzz {
+    name: "bluetoothV1.0_fuzzer",
+    vendor: true,
+    srcs: [
+        "bluetoothV1.0_fuzzer.cpp",
+    ],
+    static_libs: [
+        "android.hardware.bluetooth@1.0-impl-test",
+        "android.hardware.bluetooth-async",
+        "android.hardware.bluetooth-hci",
+        "libcutils",
+    ],
+    shared_libs: [
+        "android.hardware.bluetooth@1.0",
+        "libhardware",
+        "libhidlbase",
+        "libbt-vendor-fuzz",
+        "liblog",
+        "libutils",
+    ],
+    fuzz_config: {
+        cc: [
+            "android-media-fuzzing-reports@google.com",
+        ],
+        componentid: 533764,
+    },
+}
diff --git a/bluetooth/1.0/default/test/fuzzer/README.md b/bluetooth/1.0/default/test/fuzzer/README.md
new file mode 100644
index 0000000..edd4fb6
--- /dev/null
+++ b/bluetooth/1.0/default/test/fuzzer/README.md
@@ -0,0 +1,48 @@
+# Fuzzer for android.hardware.bluetooth@1.0-impl-test
+
+## Plugin Design Considerations
+The fuzzer plugin for android.hardware.bluetooth@1.0-impl-test is designed based on the understanding of the source code and tries to achieve the following:
+
+##### Maximize code coverage
+1. The configuration parameters are not hardcoded, but instead selected based on
+incoming data. This ensures more code paths are reached by the fuzzer.
+
+2. A new library *'libbt-vendor-fuzz.so'* is created that implements functions of `bt_vendor_interface_t` and calls them in order to maximize the code coverage
+
+android.hardware.bluetooth@1.0-impl-test supports the following parameters:
+
+1. Bluetooth Address (parameter name: `btAddress`)
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+| `btAddress` | Values inside array ranges from `0x0` to `0xFF`| Value obtained from FuzzedDataProvider|
+
+This also ensures that the plugin is always deterministic for any given input.
+
+##### Maximize utilization of input data
+The plugin feeds the entire input data to the module.
+This ensures that the plugin tolerates any kind of input (empty, huge,
+malformed, etc) and doesnt `exit()` on any input and thereby increasing the
+chance of identifying vulnerabilities.
+
+## Build
+
+This describes steps to build bluetoothV1.0_fuzzer binary.
+
+### Android
+
+#### Steps to build
+Build the fuzzer
+```
+  $ mm -j$(nproc) bluetoothV1.0_fuzzer
+```
+#### Steps to run
+To run on device
+```
+  $ adb sync data
+  $ adb shell LD_LIBRARY_PATH=/data/fuzz/${TARGET_ARCH}/lib/ /data/fuzz/${TARGET_ARCH}/bluetoothV1.0_fuzzer/bluetoothV1.0_fuzzer
+```
+
+## References:
+ * http://llvm.org/docs/LibFuzzer.html
+ * https://github.com/google/oss-fuzz
diff --git a/bluetooth/1.0/default/test/fuzzer/bluetoothV1.0_fuzzer.cpp b/bluetooth/1.0/default/test/fuzzer/bluetoothV1.0_fuzzer.cpp
new file mode 100644
index 0000000..fb8df99
--- /dev/null
+++ b/bluetooth/1.0/default/test/fuzzer/bluetoothV1.0_fuzzer.cpp
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include <android/hardware/bluetooth/1.0/IBluetoothHci.h>
+#include <android/hardware/bluetooth/1.0/IBluetoothHciCallbacks.h>
+#include <bluetooth_address.h>
+#include <bluetooth_hci.h>
+#include <cutils/properties.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <log/log.h>
+
+#include "bt_vendor.h"
+
+using namespace std;
+using ::android::sp;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::bluetooth::V1_0::IBluetoothHci;
+using ::android::hardware::bluetooth::V1_0::IBluetoothHciCallbacks;
+using ::android::hardware::bluetooth::V1_0::Status;
+using ::android::hardware::bluetooth::V1_0::implementation::BluetoothAddress;
+using ::android::hardware::bluetooth::V1_0::implementation::BluetoothHci;
+using ::android::hardware::bluetooth::V1_0::implementation::
+    FACTORY_BDADDR_PROPERTY;
+using ::android::hardware::bluetooth::V1_0::implementation::
+    PERSIST_BDADDR_PROPERTY;
+using ::android::hardware::bluetooth::V1_0::implementation::
+    PROPERTY_BT_BDADDR_PATH;
+
+constexpr size_t kMaxPacketSize = 100;
+constexpr size_t kMinFdcount = 2;
+
+template <typename T>
+const hidl_vec<T> toHidlVec(const std::vector<T>& vec) {
+  hidl_vec<T> hVec;
+  hVec.setToExternal(const_cast<T*>(vec.data()), vec.size());
+  return hVec;
+}
+
+class BluetoothHciCallbacks : public IBluetoothHciCallbacks {
+ public:
+  virtual ~BluetoothHciCallbacks() = default;
+
+  Return<void> initializationComplete(Status status) override {
+    if (status == Status::SUCCESS) {
+      isInitialized = true;
+    } else {
+      isInitialized = false;
+    }
+    return Return<void>();
+  };
+
+  Return<void> hciEventReceived(
+      const ::android::hardware::hidl_vec<uint8_t>& /*event*/) override {
+    return Return<void>();
+  };
+
+  Return<void> aclDataReceived(
+      const ::android::hardware::hidl_vec<uint8_t>& /*data*/) override {
+    return Return<void>();
+  };
+
+  Return<void> scoDataReceived(
+      const ::android::hardware::hidl_vec<uint8_t>& /*data*/) override {
+    return Return<void>();
+  };
+  bool isInitialized;
+};
+
+class BluetoothFuzzer {
+ public:
+  ~BluetoothFuzzer() {
+    if (mFdp) {
+      delete mFdp;
+    }
+    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;
+};
+
+bool BluetoothFuzzer::init(const uint8_t* data, size_t size) {
+  mBtHci = sp<BluetoothHci>::make();
+  if (!mBtHci) {
+    return false;
+  }
+  mFdp = new FuzzedDataProvider(data, size);
+  return true;
+}
+
+void BluetoothFuzzer::process() {
+  sp<BluetoothHciCallbacks> bluetoothCallback =
+      sp<BluetoothHciCallbacks>::make();
+
+  uint8_t btAddress[BluetoothAddress::kBytes];
+  mFdp->ConsumeData(btAddress, sizeof(uint8_t) * BluetoothAddress::kBytes);
+
+  char btAddrString[BluetoothAddress::kStringLength + 1];
+  BluetoothAddress::bytes_to_string(btAddress, btAddrString);
+
+  /* property_set() is called so that BluetoothAddress::get_local_address()
+   * could return true and the LOG_ALWAYS_FATAL() that aborts the run, if
+   * BluetoothAddress::get_local_address() returns false, could be avoided.
+   *
+   * BluetoothAddress::get_local_address() first searches if
+   * PROPERTY_BT_BDADDR_PATH is set, if it fails to get PROPERTY_BT_BDADDR_PATH,
+   * it searches for FACTORY_BDADDR_PROPERTY. If it fails to get
+   * FACTORY_BDADDR_PROPERTY, it then searches for PERSIST_BDADDR_PROPERTY. If
+   * PERSIST_BDADDR_PROPERTY is also not set, it results in an abort.
+   */
+  property_set(PERSIST_BDADDR_PROPERTY, btAddrString);
+
+  if (mFdp->ConsumeBool()) {
+    property_set(FACTORY_BDADDR_PROPERTY, btAddrString);
+  }
+
+  if (mFdp->ConsumeBool()) {
+    char property[PROPERTY_VALUE_MAX] = {0};
+    property_get("ro.vendor.bt.bdaddr_path", property, NULL);
+    // get the value of ro.vendor.bt.bdaddr_path and set it to
+    // PROPERTY_BT_BDADDR_PATH
+    property_set(PROPERTY_BT_BDADDR_PATH, property);
+  }
+
+  bool shouldSetH4Protocol = mFdp->ConsumeBool();
+  BtVendor* btVendor = BtVendor::getInstance();
+
+  if (!shouldSetH4Protocol) {
+    mFdCount = mFdp->ConsumeIntegralInRange<size_t>(kMinFdcount, CH_MAX - 1);
+  }
+
+  for (size_t i = 0; i < mFdCount; ++i) {
+    mFdList[i] = open("/dev/null", O_RDWR | O_CREAT);
+  }
+
+  btVendor->populateFdList(mFdList, mFdCount);
+  mBtHci->initialize(bluetoothCallback);
+
+  if (!bluetoothCallback->isInitialized) {
+    return;
+  }
+
+  std::vector<uint8_t> hciPacket, aclPacket;
+
+  size_t hciPacketSize =
+      mFdp->ConsumeIntegralInRange<size_t>(0, kMaxPacketSize);
+  hciPacket = mFdp->ConsumeBytes<uint8_t>(hciPacketSize);
+  mBtHci->sendHciCommand(toHidlVec(hciPacket));
+
+  size_t aclPacketSize =
+      mFdp->ConsumeIntegralInRange<size_t>(0, kMaxPacketSize);
+  aclPacket = mFdp->ConsumeBytes<uint8_t>(aclPacketSize);
+  mBtHci->sendAclData(toHidlVec(aclPacket));
+
+  if (shouldSetH4Protocol) {
+    std::vector<uint8_t> scoPacket;
+    size_t scoPacketSize =
+        mFdp->ConsumeIntegralInRange<size_t>(0, kMaxPacketSize);
+    scoPacket = mFdp->ConsumeBytes<uint8_t>(scoPacketSize);
+    mBtHci->sendScoData(toHidlVec(scoPacket));
+  }
+
+  btVendor->callRemainingCbacks();
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  BluetoothFuzzer bluetoothFuzzer;
+  if (bluetoothFuzzer.init(data, size)) {
+    bluetoothFuzzer.process();
+  }
+  return 0;
+}
diff --git a/bluetooth/1.0/default/test/fuzzer/bt_vendor.cpp b/bluetooth/1.0/default/test/fuzzer/bt_vendor.cpp
new file mode 100644
index 0000000..897fb67
--- /dev/null
+++ b/bluetooth/1.0/default/test/fuzzer/bt_vendor.cpp
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include "bt_vendor.h"
+
+#define UNUSED_PARAM __attribute__((unused))
+#define HCI_CMD_PREAMBLE_SIZE 3
+#define HCI_RESET 0x0C03
+#define HCI_EVT_CMD_CMPL_OPCODE 3
+#define HCI_EVT_CMD_CMPL_STATUS_RET_BYTE 5
+#define MSG_STACK_TO_HC_HCI_CMD 0x2000
+#define BT_HC_HDR_SIZE (sizeof(HC_BT_HDR))
+#define STREAM_TO_UINT16(u16, p)                                \
+  {                                                             \
+    u16 = ((uint16_t)(*(p)) + (((uint16_t)(*((p) + 1))) << 8)); \
+    (p) += 2;                                                   \
+  }
+#define UINT16_TO_STREAM(p, u16)    \
+  {                                 \
+    *(p)++ = (uint8_t)(u16);        \
+    *(p)++ = (uint8_t)((u16) >> 8); \
+  }
+bt_vendor_callbacks_t* bt_vendor_cbacks = nullptr;
+
+void hw_epilog_cback(void* p_mem) {
+  HC_BT_HDR* p_evt_buf = (HC_BT_HDR*)p_mem;
+  uint8_t *p, status;
+  uint16_t opcode;
+
+  status = *((uint8_t*)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE);
+  p = (uint8_t*)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
+  STREAM_TO_UINT16(opcode, p);
+
+  if (!bt_vendor_cbacks) {
+    return;
+  }
+  /* Must free the RX event buffer */
+  bt_vendor_cbacks->dealloc(p_evt_buf);
+
+  /* Once epilog process is done, must call callback to notify caller */
+  bt_vendor_cbacks->epilog_cb(BT_VND_OP_RESULT_SUCCESS);
+  return;
+}
+
+static int testInit(const bt_vendor_callbacks_t* cb,
+                    unsigned char* bdaddr UNUSED_PARAM) {
+  if (cb == nullptr) {
+    return -1;
+  }
+  /*store reference to user callbacks */
+  bt_vendor_cbacks = (bt_vendor_callbacks_t*)cb;
+  return 0;
+}
+
+static int testOperations(bt_vendor_opcode_t opcode, void* param UNUSED_PARAM) {
+  BtVendor* btVendor = BtVendor::getInstance();
+  if (bt_vendor_cbacks) {
+    btVendor->setVendorCback(bt_vendor_cbacks, opcode);
+  }
+  switch (opcode) {
+    case BT_VND_OP_POWER_CTRL: {
+      // No callback for this opcode
+      break;
+    }
+    case BT_VND_OP_USERIAL_OPEN: {
+      int32_t(*fd_array)[] = (int32_t(*)[])param;
+      int32_t fdArray[CH_MAX];
+      *fdArray = *(btVendor->queryFdList());
+      size_t fdcount = btVendor->queryFdCount();
+      for (size_t i = 0; i < fdcount; ++i) {
+        (*fd_array)[i] = fdArray[i];
+      }
+      return fdcount;
+      break;
+    }
+    case BT_VND_OP_FW_CFG: {
+      if (bt_vendor_cbacks) {
+        bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
+      }
+      break;
+    }
+    case BT_VND_OP_GET_LPM_IDLE_TIMEOUT: {
+      // No callback for this opcode
+      uint32_t* timeout_ms = (uint32_t*)param;
+      *timeout_ms = 0;
+      break;
+    }
+    case BT_VND_OP_LPM_SET_MODE: {
+      if (bt_vendor_cbacks) {
+        bt_vendor_cbacks->lpm_cb(BT_VND_OP_RESULT_SUCCESS);
+      }
+      break;
+    }
+    case BT_VND_OP_USERIAL_CLOSE: {
+      // No callback for this opcode
+      break;
+    }
+    case BT_VND_OP_LPM_WAKE_SET_STATE: {
+      // No callback for this opcode
+      break;
+    }
+    default:
+      break;
+  }
+  return 0;
+}
+
+static void testCleanup(void) { bt_vendor_cbacks = nullptr; }
+
+const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE = {
+    sizeof(bt_vendor_interface_t), testInit, testOperations, testCleanup};
+
+void BtVendor::populateFdList(int32_t list[], size_t count) {
+  fdCount = count;
+  for (size_t i = 0; i < count; ++i) {
+    fdList[i] = list[i];
+  }
+}
+
+void BtVendor::callRemainingCbacks() {
+  if (mCbacks) {
+    mCbacks->audio_state_cb(BT_VND_OP_RESULT_SUCCESS);
+    mCbacks->scocfg_cb(BT_VND_OP_RESULT_SUCCESS);
+    mCbacks->a2dp_offload_cb(BT_VND_OP_RESULT_SUCCESS, mOpcode, 0);
+    mCbacks->epilog_cb(BT_VND_OP_RESULT_SUCCESS);
+
+    HC_BT_HDR* p_buf = NULL;
+    uint8_t* p;
+
+    /* Sending a HCI_RESET */
+    /* Must allocate command buffer via HC's alloc API */
+    p_buf = (HC_BT_HDR*)mCbacks->alloc(BT_HC_HDR_SIZE + HCI_CMD_PREAMBLE_SIZE);
+    if (p_buf) {
+      p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
+      p_buf->offset = 0;
+      p_buf->layer_specific = 0;
+      p_buf->len = HCI_CMD_PREAMBLE_SIZE;
+
+      p = (uint8_t*)(p_buf + 1);
+      UINT16_TO_STREAM(p, HCI_RESET);
+      *p = 0; /* parameter length */
+
+      /* Send command via HC's xmit_cb API */
+      mCbacks->xmit_cb(HCI_RESET, p_buf, hw_epilog_cback);
+    } else {
+      mCbacks->epilog_cb(BT_VND_OP_RESULT_FAIL);
+    }
+  }
+}
diff --git a/bluetooth/1.0/default/test/fuzzer/bt_vendor.h b/bluetooth/1.0/default/test/fuzzer/bt_vendor.h
new file mode 100644
index 0000000..ca227ea
--- /dev/null
+++ b/bluetooth/1.0/default/test/fuzzer/bt_vendor.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#ifndef __BT_VENDOR_H__
+#define __BT_VENDOR_H__
+
+#include "bt_vendor_lib.h"
+
+class BtVendor {
+ public:
+  static BtVendor* getInstance() {
+    if (!mInstance) {
+      mInstance = new BtVendor;
+    }
+    return mInstance;
+  }
+
+  void setVendorCback(bt_vendor_callbacks_t* cb, bt_vendor_opcode_t opcode) {
+    mCbacks = cb;
+    mOpcode = opcode;
+  }
+
+  int32_t* queryFdList() { return fdList; }
+  size_t queryFdCount() { return fdCount; }
+  void callRemainingCbacks();
+  void populateFdList(int32_t list[], size_t count);
+
+ private:
+  BtVendor() = default;
+
+  ~BtVendor() {
+    if (mInstance) {
+      delete mInstance;
+      mInstance = nullptr;
+    }
+    mCbacks = nullptr;
+  }
+
+  static BtVendor* mInstance;
+  bt_vendor_callbacks_t* mCbacks = nullptr;
+  bt_vendor_opcode_t mOpcode;
+  int32_t fdCount;
+  int32_t fdList[CH_MAX] = {0};
+};
+
+BtVendor* BtVendor::mInstance = nullptr;
+#endif  // __BT_VENDOR_H__
diff --git a/bluetooth/1.0/default/vendor_interface.cc b/bluetooth/1.0/default/vendor_interface.cc
index d809313..1d15dd6 100644
--- a/bluetooth/1.0/default/vendor_interface.cc
+++ b/bluetooth/1.0/default/vendor_interface.cc
@@ -27,7 +27,11 @@
 #include "h4_protocol.h"
 #include "mct_protocol.h"
 
+#ifdef BT_FUZZER
+static const char* VENDOR_LIBRARY_NAME = "libbt-vendor-fuzz.so";
+#else
 static const char* VENDOR_LIBRARY_NAME = "libbt-vendor.so";
+#endif
 static const char* VENDOR_LIBRARY_SYMBOL_NAME =
     "BLUETOOTH_VENDOR_LIB_INTERFACE";
 
diff --git a/bluetooth/1.0/vts/functional/OWNERS b/bluetooth/1.0/vts/functional/OWNERS
new file mode 100644
index 0000000..7f02612
--- /dev/null
+++ b/bluetooth/1.0/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 27441
+bluetooth-reviews@google.com
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/vts/OWNERS b/bluetooth/a2dp/1.0/vts/OWNERS
index 58d3a66..d3aab51 100644
--- a/bluetooth/a2dp/1.0/vts/OWNERS
+++ b/bluetooth/a2dp/1.0/vts/OWNERS
@@ -1,8 +1,4 @@
-zachoverflow@google.com
-siyuanh@google.com
-mylesgw@google.com
-jpawlowski@google.com
-apanicke@google.com
-stng@google.com
-hsz@google.com
+# Bug component: 27441
+include platform/packages/modules/Bluetooth:/OWNERS
 
+cheneyni@google.com
diff --git a/bluetooth/audio/2.0/vts/OWNERS b/bluetooth/audio/2.0/vts/OWNERS
deleted file mode 100644
index b6c0813..0000000
--- a/bluetooth/audio/2.0/vts/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-include platform/system/bt:/OWNERS
-
-cheneyni@google.com
diff --git a/bluetooth/audio/2.1/Android.bp b/bluetooth/audio/2.1/Android.bp
index 822f5b3..1175fb3 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.updatable",
+        "com.android.bluetooth",
     ],
     gen_java: false,
 }
diff --git a/bluetooth/audio/2.1/default/Android.bp b/bluetooth/audio/2.1/default/Android.bp
index 5c30f79..3000223 100644
--- a/bluetooth/audio/2.1/default/Android.bp
+++ b/bluetooth/audio/2.1/default/Android.bp
@@ -19,6 +19,7 @@
         "A2dpSoftwareAudioProvider.cpp",
         "HearingAidAudioProvider.cpp",
         "LeAudioAudioProvider.cpp",
+        "LeAudioOffloadAudioProvider.cpp",
     ],
     header_libs: ["libhardware_headers"],
     shared_libs: [
diff --git a/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.cpp b/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.cpp
index e1b1ac6..6e8c1d7 100644
--- a/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.cpp
+++ b/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.cpp
@@ -147,7 +147,11 @@
         audio_capabilities[i].codecCapabilities(db_codec_capabilities[i]);
       }
     }
-  } else if (sessionType != SessionType::UNKNOWN) {
+  } else if (sessionType !=
+                 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
+             sessionType !=
+                 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH &&
+             sessionType != SessionType::UNKNOWN) {
     std::vector<PcmParameters> db_pcm_capabilities =
         android::bluetooth::audio::GetSoftwarePcmCapabilities_2_1();
     if (db_pcm_capabilities.size() == 1) {
diff --git a/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.h b/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.h
index fd83694..714d738 100644
--- a/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.h
+++ b/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.h
@@ -23,6 +23,7 @@
 #include "BluetoothAudioProvider.h"
 #include "HearingAidAudioProvider.h"
 #include "LeAudioAudioProvider.h"
+#include "LeAudioOffloadAudioProvider.h"
 
 namespace android {
 namespace hardware {
diff --git a/bluetooth/audio/2.1/default/LeAudioOffloadAudioProvider.cpp b/bluetooth/audio/2.1/default/LeAudioOffloadAudioProvider.cpp
new file mode 100644
index 0000000..c11bdad
--- /dev/null
+++ b/bluetooth/audio/2.1/default/LeAudioOffloadAudioProvider.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "BTAudioProviderLeAudioOffload"
+
+#include "LeAudioOffloadAudioProvider.h"
+
+#include <android-base/logging.h>
+
+#include "BluetoothAudioSessionReport_2_1.h"
+#include "BluetoothAudioSupportedCodecsDB_2_1.h"
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::bluetooth::audio::BluetoothAudioSessionReport_2_1;
+using ::android::hardware::Void;
+using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
+using ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
+using ::android::hardware::bluetooth::audio::V2_1::SampleRate;
+
+using DataMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+
+LeAudioOffloadOutputAudioProvider::LeAudioOffloadOutputAudioProvider()
+    : LeAudioOffloadAudioProvider() {
+  session_type_ = SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
+}
+
+LeAudioOffloadInputAudioProvider::LeAudioOffloadInputAudioProvider()
+    : LeAudioOffloadAudioProvider() {
+  session_type_ = SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH;
+}
+
+LeAudioOffloadAudioProvider::LeAudioOffloadAudioProvider()
+    : BluetoothAudioProvider() {}
+
+bool LeAudioOffloadAudioProvider::isValid(const V2_0::SessionType& sessionType) {
+  LOG(ERROR) << __func__ << ", invalid session type for Offloaded Le Audio provider: "
+             << toString(sessionType);
+
+  return false;
+}
+
+bool LeAudioOffloadAudioProvider::isValid(const SessionType& sessionType) {
+  return (sessionType == session_type_);
+}
+
+Return<void> LeAudioOffloadAudioProvider::startSession_2_1(
+    const sp<V2_0::IBluetoothAudioPort>& hostIf,
+    const AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
+  /**
+   * Initialize the audio platform if audioConfiguration is supported.
+   * Save the IBluetoothAudioPort interface, so that it can be used
+   * later to send stream control commands to the HAL client, based on
+   * interaction with Audio framework.
+   */
+  if (audioConfig.getDiscriminator() !=
+      AudioConfiguration::hidl_discriminator::leAudioCodecConfig) {
+    LOG(WARNING) << __func__
+                 << " - Invalid Audio Configuration=" << toString(audioConfig);
+    _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
+             DataMQ::Descriptor());
+    return Void();
+  }
+
+  if (!android::bluetooth::audio::IsOffloadLeAudioConfigurationValid(session_type_,
+                 audioConfig.leAudioCodecConfig())) {
+    LOG(WARNING) << __func__ << " - Unsupported LC3 Offloaded Configuration="
+                 << toString(audioConfig.leAudioCodecConfig());
+    _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
+             DataMQ::Descriptor());
+    return Void();
+  }
+
+  return BluetoothAudioProvider::startSession_2_1(hostIf, audioConfig,
+                                                  _hidl_cb);
+}
+
+Return<void> LeAudioOffloadAudioProvider::onSessionReady(startSession_cb _hidl_cb) {
+  BluetoothAudioSessionReport_2_1::OnSessionStarted(session_type_, stack_iface_,
+                                                    nullptr, audio_config_);
+  _hidl_cb(BluetoothAudioStatus::SUCCESS, DataMQ::Descriptor());
+  return Void();
+}
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
diff --git a/bluetooth/audio/2.1/default/LeAudioOffloadAudioProvider.h b/bluetooth/audio/2.1/default/LeAudioOffloadAudioProvider.h
new file mode 100644
index 0000000..564e9a3
--- /dev/null
+++ b/bluetooth/audio/2.1/default/LeAudioOffloadAudioProvider.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/hardware/bluetooth/audio/2.1/types.h>
+
+#include "BluetoothAudioProvider.h"
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+namespace V2_1 {
+namespace implementation {
+
+class LeAudioOffloadAudioProvider : public BluetoothAudioProvider {
+ public:
+  LeAudioOffloadAudioProvider();
+
+  bool isValid(const SessionType& sessionType) override;
+  bool isValid(const V2_0::SessionType& sessionType) override;
+
+  Return<void> startSession_2_1(const sp<V2_0::IBluetoothAudioPort>& hostIf,
+                                const AudioConfiguration& audioConfig,
+                                startSession_cb _hidl_cb) override;
+
+ private:
+  Return<void> onSessionReady(startSession_cb _hidl_cb) override;
+};
+
+class LeAudioOffloadOutputAudioProvider : public LeAudioOffloadAudioProvider {
+ public:
+  LeAudioOffloadOutputAudioProvider();
+};
+
+class LeAudioOffloadInputAudioProvider : public LeAudioOffloadAudioProvider {
+ public:
+  LeAudioOffloadInputAudioProvider();
+};
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
diff --git a/bluetooth/audio/2.1/vts/OWNERS b/bluetooth/audio/2.1/vts/OWNERS
deleted file mode 100644
index b6c0813..0000000
--- a/bluetooth/audio/2.1/vts/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-include platform/system/bt:/OWNERS
-
-cheneyni@google.com
diff --git a/bluetooth/audio/2.1/vts/functional/Android.bp b/bluetooth/audio/2.1/vts/functional/Android.bp
index 3314a8a..cea7326 100644
--- a/bluetooth/audio/2.1/vts/functional/Android.bp
+++ b/bluetooth/audio/2.1/vts/functional/Android.bp
@@ -10,6 +10,7 @@
 cc_test {
     name: "VtsHalBluetoothAudioV2_1TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: ["VtsHalBluetoothAudioV2_1TargetTest.cpp"],
     srcs: ["VtsHalBluetoothAudioV2_1TargetTest.cpp"],
     static_libs: [
         "android.hardware.audio.common@5.0",
diff --git a/bluetooth/audio/OWNERS b/bluetooth/audio/OWNERS
new file mode 100644
index 0000000..a8e9bda
--- /dev/null
+++ b/bluetooth/audio/OWNERS
@@ -0,0 +1,4 @@
+include platform/packages/modules/Bluetooth:/OWNERS
+
+cheneyni@google.com
+aliceypkuo@google.com
diff --git a/bluetooth/audio/aidl/Android.bp b/bluetooth/audio/aidl/Android.bp
new file mode 100644
index 0000000..52671b8
--- /dev/null
+++ b/bluetooth/audio/aidl/Android.bp
@@ -0,0 +1,53 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+aidl_interface {
+    name: "android.hardware.bluetooth.audio",
+    vendor_available: true,
+    srcs: ["android/hardware/bluetooth/audio/*.aidl"],
+    stability: "vintf",
+    imports: [
+        "android.hardware.common-V2",
+        "android.hardware.common.fmq-V1",
+        "android.hardware.audio.common",
+    ],
+    backend: {
+        cpp: {
+            enabled: false,
+        },
+        java: {
+            sdk_version: "module_current",
+            enabled: false,
+        },
+        ndk: {
+            vndk: {
+                enabled: true,
+            },
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.bluetooth",
+            ],
+            min_sdk_version: "31",
+        },
+    },
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AacCapabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AacCapabilities.aidl
new file mode 100644
index 0000000..899b8ca
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AacCapabilities.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@VintfStability
+parcelable AacCapabilities {
+  android.hardware.bluetooth.audio.AacObjectType[] objectType;
+  int[] sampleRateHz;
+  android.hardware.bluetooth.audio.ChannelMode[] channelMode;
+  boolean variableBitRateSupported;
+  byte[] bitsPerSample;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AacConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AacConfiguration.aidl
new file mode 100644
index 0000000..6adef6d
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AacConfiguration.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@VintfStability
+parcelable AacConfiguration {
+  android.hardware.bluetooth.audio.AacObjectType objectType;
+  int sampleRateHz;
+  android.hardware.bluetooth.audio.ChannelMode channelMode;
+  boolean variableBitRateEnabled;
+  byte bitsPerSample;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AacObjectType.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AacObjectType.aidl
new file mode 100644
index 0000000..2148244
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AacObjectType.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@Backing(type="byte") @VintfStability
+enum AacObjectType {
+  MPEG2_LC = 0,
+  MPEG4_LC = 1,
+  MPEG4_LTP = 2,
+  MPEG4_SCALABLE = 3,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxAdaptiveCapabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxAdaptiveCapabilities.aidl
new file mode 100644
index 0000000..4e5dfe6
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxAdaptiveCapabilities.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@VintfStability
+parcelable AptxAdaptiveCapabilities {
+  int[] sampleRateHz;
+  android.hardware.bluetooth.audio.AptxAdaptiveChannelMode[] channelMode;
+  byte[] bitsPerSample;
+  android.hardware.bluetooth.audio.AptxMode[] aptxMode;
+  android.hardware.bluetooth.audio.AptxSinkBuffering sinkBufferingMs;
+  android.hardware.bluetooth.audio.AptxAdaptiveTimeToPlay ttp;
+  android.hardware.bluetooth.audio.AptxAdaptiveInputMode inputMode;
+  int inputFadeDurationMs;
+  byte[] aptxAdaptiveConfigStream;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxAdaptiveChannelMode.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxAdaptiveChannelMode.aidl
new file mode 100644
index 0000000..0499b70
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxAdaptiveChannelMode.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@Backing(type="int") @VintfStability
+enum AptxAdaptiveChannelMode {
+  JOINT_STEREO = 0,
+  MONO = 1,
+  DUAL_MONO = 2,
+  TWS_STEREO = 4,
+  UNKNOWN = 255,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxAdaptiveConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxAdaptiveConfiguration.aidl
new file mode 100644
index 0000000..aab0521
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxAdaptiveConfiguration.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@VintfStability
+parcelable AptxAdaptiveConfiguration {
+  int sampleRateHz;
+  android.hardware.bluetooth.audio.AptxAdaptiveChannelMode channelMode;
+  byte bitsPerSample;
+  android.hardware.bluetooth.audio.AptxMode aptxMode;
+  android.hardware.bluetooth.audio.AptxSinkBuffering sinkBufferingMs;
+  android.hardware.bluetooth.audio.AptxAdaptiveTimeToPlay ttp;
+  android.hardware.bluetooth.audio.AptxAdaptiveInputMode inputMode;
+  int inputFadeDurationMs;
+  byte[] aptxAdaptiveConfigStream;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxAdaptiveInputMode.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxAdaptiveInputMode.aidl
new file mode 100644
index 0000000..f702939
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxAdaptiveInputMode.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@Backing(type="int") @VintfStability
+enum AptxAdaptiveInputMode {
+  STEREO = 0,
+  DUAL_MONO = 1,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxAdaptiveTimeToPlay.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxAdaptiveTimeToPlay.aidl
new file mode 100644
index 0000000..3560666
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxAdaptiveTimeToPlay.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@VintfStability
+parcelable AptxAdaptiveTimeToPlay {
+  byte lowLowLatency;
+  byte highLowLatency;
+  byte lowHighQuality;
+  byte highHighQuality;
+  byte lowTws;
+  byte highTws;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxCapabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxCapabilities.aidl
new file mode 100644
index 0000000..08a38e2
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxCapabilities.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@VintfStability
+parcelable AptxCapabilities {
+  int[] sampleRateHz;
+  android.hardware.bluetooth.audio.ChannelMode[] channelMode;
+  byte[] bitsPerSample;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxConfiguration.aidl
new file mode 100644
index 0000000..91e88b3
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxConfiguration.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@VintfStability
+parcelable AptxConfiguration {
+  int sampleRateHz;
+  android.hardware.bluetooth.audio.ChannelMode channelMode;
+  byte bitsPerSample;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxMode.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxMode.aidl
new file mode 100644
index 0000000..d5dd9d9
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxMode.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@Backing(type="int") @VintfStability
+enum AptxMode {
+  UNKNOWN = 0,
+  HIGH_QUALITY = 4096,
+  LOW_LATENCY = 8192,
+  ULTRA_LOW_LATENCY = 16384,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxSinkBuffering.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxSinkBuffering.aidl
new file mode 100644
index 0000000..527418e
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AptxSinkBuffering.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@VintfStability
+parcelable AptxSinkBuffering {
+  byte minLowLatency;
+  byte maxLowLatency;
+  byte minHighQuality;
+  byte maxHighQuality;
+  byte minTws;
+  byte maxTws;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AudioCapabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AudioCapabilities.aidl
new file mode 100644
index 0000000..8ae716f
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AudioCapabilities.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@VintfStability
+union AudioCapabilities {
+  android.hardware.bluetooth.audio.PcmCapabilities pcmCapabilities;
+  android.hardware.bluetooth.audio.CodecCapabilities a2dpCapabilities;
+  android.hardware.bluetooth.audio.LeAudioCodecCapabilitiesSetting leAudioCapabilities;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AudioConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AudioConfiguration.aidl
new file mode 100644
index 0000000..3abfb31
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AudioConfiguration.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@VintfStability
+union AudioConfiguration {
+  android.hardware.bluetooth.audio.PcmConfiguration pcmConfig;
+  android.hardware.bluetooth.audio.CodecConfiguration a2dpConfig;
+  android.hardware.bluetooth.audio.LeAudioConfiguration leAudioConfig;
+  android.hardware.bluetooth.audio.LeAudioBroadcastConfiguration leAudioBroadcastConfig;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AudioLocation.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AudioLocation.aidl
new file mode 100644
index 0000000..319a5e2
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/AudioLocation.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@Backing(type="int") @VintfStability
+enum AudioLocation {
+  UNKNOWN = 1,
+  FRONT_LEFT = 2,
+  FRONT_RIGHT = 4,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/BluetoothAudioStatus.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/BluetoothAudioStatus.aidl
new file mode 100644
index 0000000..c20c057
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/BluetoothAudioStatus.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@Backing(type="int") @VintfStability
+enum BluetoothAudioStatus {
+  UNKNOWN = 0,
+  SUCCESS = 1,
+  UNSUPPORTED_CODEC_CONFIGURATION = 2,
+  FAILURE = 3,
+  RECONFIGURATION = 4,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/BroadcastCapability.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/BroadcastCapability.aidl
new file mode 100644
index 0000000..58710ef
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/BroadcastCapability.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@VintfStability
+parcelable BroadcastCapability {
+  android.hardware.bluetooth.audio.CodecType codecType;
+  android.hardware.bluetooth.audio.AudioLocation supportedChannel;
+  int channelCountPerStream;
+  android.hardware.bluetooth.audio.BroadcastCapability.LeAudioCodecCapabilities leAudioCodecCapabilities;
+  @VintfStability
+  parcelable VendorCapabilities {
+    ParcelableHolder extension;
+  }
+  @VintfStability
+  union LeAudioCodecCapabilities {
+    @nullable android.hardware.bluetooth.audio.Lc3Capabilities[] lc3Capabilities;
+    @nullable android.hardware.bluetooth.audio.BroadcastCapability.VendorCapabilities[] vendorCapabillities;
+  }
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/ChannelMode.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/ChannelMode.aidl
new file mode 100644
index 0000000..c3bc741
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/ChannelMode.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@Backing(type="byte") @VintfStability
+enum ChannelMode {
+  UNKNOWN = 0,
+  MONO = 1,
+  STEREO = 2,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecCapabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecCapabilities.aidl
new file mode 100644
index 0000000..6efdcb7
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecCapabilities.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@VintfStability
+parcelable CodecCapabilities {
+  android.hardware.bluetooth.audio.CodecType codecType;
+  android.hardware.bluetooth.audio.CodecCapabilities.Capabilities capabilities;
+  @VintfStability
+  parcelable VendorCapabilities {
+    ParcelableHolder extension;
+  }
+  @VintfStability
+  union Capabilities {
+    android.hardware.bluetooth.audio.SbcCapabilities sbcCapabilities;
+    android.hardware.bluetooth.audio.AacCapabilities aacCapabilities;
+    android.hardware.bluetooth.audio.LdacCapabilities ldacCapabilities;
+    android.hardware.bluetooth.audio.AptxCapabilities aptxCapabilities;
+    android.hardware.bluetooth.audio.AptxAdaptiveCapabilities aptxAdaptiveCapabilities;
+    android.hardware.bluetooth.audio.Lc3Capabilities lc3Capabilities;
+    android.hardware.bluetooth.audio.CodecCapabilities.VendorCapabilities vendorCapabilities;
+  }
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecConfiguration.aidl
new file mode 100644
index 0000000..77a6b1b
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecConfiguration.aidl
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@VintfStability
+parcelable CodecConfiguration {
+  android.hardware.bluetooth.audio.CodecType codecType;
+  int encodedAudioBitrate;
+  int peerMtu;
+  boolean isScmstEnabled;
+  android.hardware.bluetooth.audio.CodecConfiguration.CodecSpecific config;
+  @VintfStability
+  parcelable VendorConfiguration {
+    int vendorId;
+    char codecId;
+    ParcelableHolder codecConfig;
+  }
+  @VintfStability
+  union CodecSpecific {
+    android.hardware.bluetooth.audio.SbcConfiguration sbcConfig;
+    android.hardware.bluetooth.audio.AacConfiguration aacConfig;
+    android.hardware.bluetooth.audio.LdacConfiguration ldacConfig;
+    android.hardware.bluetooth.audio.AptxConfiguration aptxConfig;
+    android.hardware.bluetooth.audio.AptxAdaptiveConfiguration aptxAdaptiveConfig;
+    android.hardware.bluetooth.audio.Lc3Configuration lc3Config;
+    android.hardware.bluetooth.audio.CodecConfiguration.VendorConfiguration vendorConfig;
+  }
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecType.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecType.aidl
new file mode 100644
index 0000000..1522cb4
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/CodecType.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@Backing(type="int") @VintfStability
+enum CodecType {
+  UNKNOWN = 0,
+  SBC = 1,
+  AAC = 2,
+  APTX = 3,
+  APTX_HD = 4,
+  LDAC = 5,
+  LC3 = 6,
+  VENDOR = 7,
+  APTX_ADAPTIVE = 8,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl
new file mode 100644
index 0000000..d364371
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@VintfStability
+interface IBluetoothAudioPort {
+  android.hardware.bluetooth.audio.PresentationPosition getPresentationPosition();
+  void startStream(boolean isLowLatency);
+  void stopStream();
+  void suspendStream();
+  void updateSourceMetadata(in android.hardware.audio.common.SourceMetadata sourceMetadata);
+  void updateSinkMetadata(in android.hardware.audio.common.SinkMetadata sinkMetadata);
+  void setLatencyMode(in android.hardware.bluetooth.audio.LatencyMode latencyMode);
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl
new file mode 100644
index 0000000..267af0f
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@VintfStability
+interface IBluetoothAudioProvider {
+  void endSession();
+  android.hardware.common.fmq.MQDescriptor<byte,android.hardware.common.fmq.SynchronizedReadWrite> startSession(in android.hardware.bluetooth.audio.IBluetoothAudioPort hostIf, in android.hardware.bluetooth.audio.AudioConfiguration audioConfig, in android.hardware.bluetooth.audio.LatencyMode[] supportedLatencyModes);
+  void streamStarted(in android.hardware.bluetooth.audio.BluetoothAudioStatus status);
+  void streamSuspended(in android.hardware.bluetooth.audio.BluetoothAudioStatus status);
+  void updateAudioConfiguration(in android.hardware.bluetooth.audio.AudioConfiguration audioConfig);
+  void setLowLatencyModeAllowed(in boolean allowed);
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.aidl
new file mode 100644
index 0000000..5e33deb
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@VintfStability
+interface IBluetoothAudioProviderFactory {
+  android.hardware.bluetooth.audio.AudioCapabilities[] getProviderCapabilities(in android.hardware.bluetooth.audio.SessionType sessionType);
+  android.hardware.bluetooth.audio.IBluetoothAudioProvider openProvider(in android.hardware.bluetooth.audio.SessionType sessionType);
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LatencyMode.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LatencyMode.aidl
new file mode 100644
index 0000000..5583679
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LatencyMode.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@Backing(type="int") @VintfStability
+enum LatencyMode {
+  UNKNOWN = 0,
+  LOW_LATENCY = 1,
+  FREE = 2,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/Lc3Capabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/Lc3Capabilities.aidl
new file mode 100644
index 0000000..cc4449a
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/Lc3Capabilities.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@VintfStability
+parcelable Lc3Capabilities {
+  byte[] pcmBitDepth;
+  int[] samplingFrequencyHz;
+  int[] frameDurationUs;
+  int[] octetsPerFrame;
+  byte[] blocksPerSdu;
+  android.hardware.bluetooth.audio.ChannelMode[] channelMode;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/Lc3Configuration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/Lc3Configuration.aidl
new file mode 100644
index 0000000..7e8dccf
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/Lc3Configuration.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@VintfStability
+parcelable Lc3Configuration {
+  byte pcmBitDepth;
+  int samplingFrequencyHz;
+  int frameDurationUs;
+  int octetsPerFrame;
+  byte blocksPerSdu;
+  android.hardware.bluetooth.audio.ChannelMode channelMode;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacCapabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacCapabilities.aidl
new file mode 100644
index 0000000..aa4e4c8
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacCapabilities.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@VintfStability
+parcelable LdacCapabilities {
+  int[] sampleRateHz;
+  android.hardware.bluetooth.audio.LdacChannelMode[] channelMode;
+  android.hardware.bluetooth.audio.LdacQualityIndex[] qualityIndex;
+  byte[] bitsPerSample;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacChannelMode.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacChannelMode.aidl
new file mode 100644
index 0000000..88d6faf
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacChannelMode.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@Backing(type="byte") @VintfStability
+enum LdacChannelMode {
+  UNKNOWN = 0,
+  STEREO = 1,
+  DUAL = 2,
+  MONO = 3,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacConfiguration.aidl
new file mode 100644
index 0000000..8a37638
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacConfiguration.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@VintfStability
+parcelable LdacConfiguration {
+  int sampleRateHz;
+  android.hardware.bluetooth.audio.LdacChannelMode channelMode;
+  android.hardware.bluetooth.audio.LdacQualityIndex qualityIndex;
+  byte bitsPerSample;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacQualityIndex.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacQualityIndex.aidl
new file mode 100644
index 0000000..35e4358
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LdacQualityIndex.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@Backing(type="byte") @VintfStability
+enum LdacQualityIndex {
+  HIGH = 0,
+  MID = 1,
+  LOW = 2,
+  ABR = 3,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioBroadcastConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioBroadcastConfiguration.aidl
new file mode 100644
index 0000000..7d53b0c
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioBroadcastConfiguration.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@VintfStability
+parcelable LeAudioBroadcastConfiguration {
+  android.hardware.bluetooth.audio.CodecType codecType;
+  android.hardware.bluetooth.audio.LeAudioBroadcastConfiguration.BroadcastStreamMap[] streamMap;
+  @VintfStability
+  parcelable BroadcastStreamMap {
+    char streamHandle;
+    int audioChannelAllocation;
+    android.hardware.bluetooth.audio.LeAudioCodecConfiguration leAudioCodecConfig;
+  }
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioCodecCapabilitiesSetting.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioCodecCapabilitiesSetting.aidl
new file mode 100644
index 0000000..9818d54
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioCodecCapabilitiesSetting.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@VintfStability
+parcelable LeAudioCodecCapabilitiesSetting {
+  android.hardware.bluetooth.audio.UnicastCapability unicastEncodeCapability;
+  android.hardware.bluetooth.audio.UnicastCapability unicastDecodeCapability;
+  android.hardware.bluetooth.audio.BroadcastCapability broadcastCapability;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioCodecConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioCodecConfiguration.aidl
new file mode 100644
index 0000000..bb3d7e4
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioCodecConfiguration.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@VintfStability
+union LeAudioCodecConfiguration {
+  android.hardware.bluetooth.audio.Lc3Configuration lc3Config;
+  android.hardware.bluetooth.audio.LeAudioCodecConfiguration.VendorConfiguration vendorConfig;
+  @VintfStability
+  parcelable VendorConfiguration {
+    ParcelableHolder extension;
+  }
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioConfiguration.aidl
new file mode 100644
index 0000000..edb6795
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/LeAudioConfiguration.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@VintfStability
+parcelable LeAudioConfiguration {
+  android.hardware.bluetooth.audio.CodecType codecType;
+  android.hardware.bluetooth.audio.LeAudioConfiguration.StreamMap[] streamMap;
+  int peerDelayUs;
+  android.hardware.bluetooth.audio.LeAudioCodecConfiguration leAudioCodecConfig;
+  @VintfStability
+  parcelable StreamMap {
+    char streamHandle;
+    int audioChannelAllocation;
+  }
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/PcmCapabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/PcmCapabilities.aidl
new file mode 100644
index 0000000..0c2f87d
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/PcmCapabilities.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@VintfStability
+parcelable PcmCapabilities {
+  int[] sampleRateHz;
+  android.hardware.bluetooth.audio.ChannelMode[] channelMode;
+  byte[] bitsPerSample;
+  int[] dataIntervalUs;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/PcmConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/PcmConfiguration.aidl
new file mode 100644
index 0000000..93d7805
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/PcmConfiguration.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@VintfStability
+parcelable PcmConfiguration {
+  int sampleRateHz;
+  android.hardware.bluetooth.audio.ChannelMode channelMode;
+  byte bitsPerSample;
+  int dataIntervalUs;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/PresentationPosition.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/PresentationPosition.aidl
new file mode 100644
index 0000000..7e997e8
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/PresentationPosition.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.bluetooth.audio;
+@VintfStability
+parcelable PresentationPosition {
+  long remoteDeviceAudioDelayNanos;
+  long transmittedOctets;
+  android.hardware.bluetooth.audio.PresentationPosition.TimeSpec transmittedOctetsTimestamp;
+  @VintfStability
+  parcelable TimeSpec {
+    long tvSec;
+    long tvNSec;
+  }
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcAllocMethod.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcAllocMethod.aidl
new file mode 100644
index 0000000..091f6d7
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcAllocMethod.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@Backing(type="byte") @VintfStability
+enum SbcAllocMethod {
+  ALLOC_MD_S = 0,
+  ALLOC_MD_L = 1,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcCapabilities.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcCapabilities.aidl
new file mode 100644
index 0000000..c8d7e7e
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcCapabilities.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@VintfStability
+parcelable SbcCapabilities {
+  int[] sampleRateHz;
+  android.hardware.bluetooth.audio.SbcChannelMode[] channelMode;
+  byte[] blockLength;
+  byte[] numSubbands;
+  android.hardware.bluetooth.audio.SbcAllocMethod[] allocMethod;
+  byte[] bitsPerSample;
+  int minBitpool;
+  int maxBitpool;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcChannelMode.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcChannelMode.aidl
new file mode 100644
index 0000000..6441a99
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcChannelMode.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@Backing(type="byte") @VintfStability
+enum SbcChannelMode {
+  UNKNOWN = 0,
+  JOINT_STEREO = 1,
+  STEREO = 2,
+  DUAL = 3,
+  MONO = 4,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcConfiguration.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcConfiguration.aidl
new file mode 100644
index 0000000..8eab9c3
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SbcConfiguration.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@VintfStability
+parcelable SbcConfiguration {
+  int sampleRateHz;
+  android.hardware.bluetooth.audio.SbcChannelMode channelMode;
+  byte blockLength;
+  byte numSubbands;
+  android.hardware.bluetooth.audio.SbcAllocMethod allocMethod;
+  byte bitsPerSample;
+  int minBitpool;
+  int maxBitpool;
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SessionType.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SessionType.aidl
new file mode 100644
index 0000000..33a3187
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/SessionType.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@Backing(type="byte") @VintfStability
+enum SessionType {
+  UNKNOWN = 0,
+  A2DP_SOFTWARE_ENCODING_DATAPATH = 1,
+  A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH = 2,
+  HEARING_AID_SOFTWARE_ENCODING_DATAPATH = 3,
+  LE_AUDIO_SOFTWARE_ENCODING_DATAPATH = 4,
+  LE_AUDIO_SOFTWARE_DECODING_DATAPATH = 5,
+  LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH = 6,
+  LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH = 7,
+  LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH = 8,
+  LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH = 9,
+  A2DP_SOFTWARE_DECODING_DATAPATH = 10,
+  A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH = 11,
+}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/UnicastCapability.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/UnicastCapability.aidl
new file mode 100644
index 0000000..130fef9
--- /dev/null
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/UnicastCapability.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.bluetooth.audio;
+@VintfStability
+parcelable UnicastCapability {
+  android.hardware.bluetooth.audio.CodecType codecType;
+  android.hardware.bluetooth.audio.AudioLocation supportedChannel;
+  int deviceCount;
+  int channelCountPerDevice;
+  android.hardware.bluetooth.audio.UnicastCapability.LeAudioCodecCapabilities leAudioCodecCapabilities;
+  @VintfStability
+  parcelable VendorCapabilities {
+    ParcelableHolder extension;
+  }
+  @VintfStability
+  union LeAudioCodecCapabilities {
+    android.hardware.bluetooth.audio.Lc3Capabilities lc3Capabilities;
+    android.hardware.bluetooth.audio.UnicastCapability.VendorCapabilities vendorCapabillities;
+  }
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacCapabilities.aidl
new file mode 100644
index 0000000..c4153e9
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacCapabilities.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.AacObjectType;
+import android.hardware.bluetooth.audio.ChannelMode;
+
+/**
+ * Used for Hardware Encoding AAC codec capabilities
+ */
+@VintfStability
+parcelable AacCapabilities {
+    AacObjectType[] objectType;
+    int[] sampleRateHz;
+    ChannelMode[] channelMode;
+    boolean variableBitRateSupported;
+    byte[] bitsPerSample;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacConfiguration.aidl
new file mode 100644
index 0000000..30338e7
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacConfiguration.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.AacObjectType;
+import android.hardware.bluetooth.audio.ChannelMode;
+
+/**
+ * Used for Hardware Encoding AAC codec configuration
+ */
+@VintfStability
+parcelable AacConfiguration {
+    AacObjectType objectType;
+    int sampleRateHz;
+    ChannelMode channelMode;
+    boolean variableBitRateEnabled;
+    byte bitsPerSample;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacObjectType.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacObjectType.aidl
new file mode 100644
index 0000000..4e9958c
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AacObjectType.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+@VintfStability
+@Backing(type="byte")
+enum AacObjectType {
+    /**
+     * MPEG-2 Low Complexity. Support is Mandatory.
+     */
+    MPEG2_LC,
+    /**
+     * MPEG-4 Low Complexity. Support is Optional.
+     */
+    MPEG4_LC,
+    /**
+     * MPEG-4 Long Term Prediction. Support is Optional.
+     */
+    MPEG4_LTP,
+    /**
+     * MPEG-4 Scalable. Support is Optional.
+     */
+    MPEG4_SCALABLE,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxAdaptiveCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxAdaptiveCapabilities.aidl
new file mode 100644
index 0000000..6a56704
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxAdaptiveCapabilities.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.AptxAdaptiveChannelMode;
+import android.hardware.bluetooth.audio.AptxMode;
+import android.hardware.bluetooth.audio.AptxSinkBuffering;
+import android.hardware.bluetooth.audio.AptxAdaptiveTimeToPlay;
+import android.hardware.bluetooth.audio.AptxAdaptiveInputMode;
+
+
+@VintfStability
+parcelable AptxAdaptiveCapabilities {
+    int[] sampleRateHz;
+    AptxAdaptiveChannelMode[] channelMode;
+    byte[] bitsPerSample;
+    AptxMode[] aptxMode;
+    AptxSinkBuffering sinkBufferingMs;
+    AptxAdaptiveTimeToPlay ttp;
+    AptxAdaptiveInputMode inputMode;
+    int inputFadeDurationMs;
+    byte[] aptxAdaptiveConfigStream;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxAdaptiveChannelMode.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxAdaptiveChannelMode.aidl
new file mode 100644
index 0000000..c5e89b1
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxAdaptiveChannelMode.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+@VintfStability
+@Backing(type="int")
+enum AptxAdaptiveChannelMode {
+    /* Joint Stereo - default mode */
+    JOINT_STEREO = 0,
+    /* Legacy Mono */
+    MONO = 1,
+    /* Two streams L & R in a single channel (TWS) */
+    DUAL_MONO = 2,
+    /* Stereo - For TWS+ where L and R are different links */
+    TWS_STEREO = 4,
+    UNKNOWN = 0xFF,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxAdaptiveConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxAdaptiveConfiguration.aidl
new file mode 100644
index 0000000..84c3119
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxAdaptiveConfiguration.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.AptxAdaptiveChannelMode;
+import android.hardware.bluetooth.audio.AptxMode;
+import android.hardware.bluetooth.audio.AptxSinkBuffering;
+import android.hardware.bluetooth.audio.AptxAdaptiveTimeToPlay;
+import android.hardware.bluetooth.audio.AptxAdaptiveInputMode;
+
+@VintfStability
+parcelable AptxAdaptiveConfiguration {
+    int sampleRateHz;
+    AptxAdaptiveChannelMode channelMode;
+    byte bitsPerSample;
+    AptxMode aptxMode;
+    AptxSinkBuffering sinkBufferingMs;
+    AptxAdaptiveTimeToPlay ttp;
+    AptxAdaptiveInputMode inputMode;
+    int inputFadeDurationMs;
+    byte[] aptxAdaptiveConfigStream;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxAdaptiveInputMode.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxAdaptiveInputMode.aidl
new file mode 100644
index 0000000..c2f0fc9
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxAdaptiveInputMode.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+@VintfStability
+@Backing(type="int")
+enum AptxAdaptiveInputMode {
+    STEREO = 0x00,
+    DUAL_MONO = 0x01,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxAdaptiveTimeToPlay.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxAdaptiveTimeToPlay.aidl
new file mode 100644
index 0000000..9bcf1a4
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxAdaptiveTimeToPlay.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+@VintfStability
+parcelable AptxAdaptiveTimeToPlay {
+    byte lowLowLatency;
+    byte highLowLatency;
+    byte lowHighQuality;
+    byte highHighQuality;
+    byte lowTws;
+    byte highTws;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxCapabilities.aidl
new file mode 100644
index 0000000..f5605d3
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxCapabilities.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.ChannelMode;
+
+/**
+ * Used for Hardware Encoding AptX and AptX-HD codec capabilities
+ */
+@VintfStability
+parcelable AptxCapabilities {
+    int[] sampleRateHz;
+    ChannelMode[] channelMode;
+    byte[] bitsPerSample;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxConfiguration.aidl
new file mode 100644
index 0000000..83b7b0c
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxConfiguration.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.ChannelMode;
+
+/**
+ * Used for Hardware Encoding AptX and AptX-HD codec configuration
+ */
+@VintfStability
+parcelable AptxConfiguration {
+    int sampleRateHz;
+    ChannelMode channelMode;
+    byte bitsPerSample;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxMode.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxMode.aidl
new file mode 100644
index 0000000..2422d69
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxMode.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.bluetooth.audio;
+@VintfStability
+@Backing(type="int")
+enum AptxMode {
+    UNKNOWN = 0x00,
+    HIGH_QUALITY = 0x1000,
+    LOW_LATENCY = 0x2000,
+    ULTRA_LOW_LATENCY = 0x4000,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxSinkBuffering.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxSinkBuffering.aidl
new file mode 100644
index 0000000..3593b5d
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AptxSinkBuffering.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+@VintfStability
+parcelable AptxSinkBuffering {
+    byte minLowLatency;
+    byte maxLowLatency;
+    byte minHighQuality;
+    byte maxHighQuality;
+    byte minTws;
+    byte maxTws;
+}
+
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AudioCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AudioCapabilities.aidl
new file mode 100644
index 0000000..a75c445
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AudioCapabilities.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.CodecCapabilities;
+import android.hardware.bluetooth.audio.LeAudioCodecCapabilitiesSetting;
+import android.hardware.bluetooth.audio.PcmCapabilities;
+
+/**
+ * Used to specify the capabilities of the different session types
+ */
+@VintfStability
+union AudioCapabilities {
+    PcmCapabilities pcmCapabilities;
+    CodecCapabilities a2dpCapabilities;
+    LeAudioCodecCapabilitiesSetting leAudioCapabilities;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AudioConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AudioConfiguration.aidl
new file mode 100644
index 0000000..a06337e
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AudioConfiguration.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.CodecConfiguration;
+import android.hardware.bluetooth.audio.LeAudioBroadcastConfiguration;
+import android.hardware.bluetooth.audio.LeAudioConfiguration;
+import android.hardware.bluetooth.audio.PcmConfiguration;
+
+/**
+ * Used to configure either a Hardware or Software Encoding session based on session type
+ */
+@VintfStability
+union AudioConfiguration {
+    PcmConfiguration pcmConfig;
+    CodecConfiguration a2dpConfig;
+    LeAudioConfiguration leAudioConfig;
+    LeAudioBroadcastConfiguration leAudioBroadcastConfig;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AudioLocation.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AudioLocation.aidl
new file mode 100644
index 0000000..dedfbf9
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/AudioLocation.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+@VintfStability
+@Backing(type="int")
+enum AudioLocation {
+    UNKNOWN = 1,
+    FRONT_LEFT = 1 << 1,
+    FRONT_RIGHT = 1 << 2,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/BluetoothAudioStatus.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/BluetoothAudioStatus.aidl
new file mode 100644
index 0000000..9ddafe9
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/BluetoothAudioStatus.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+@VintfStability
+@Backing(type="int")
+enum BluetoothAudioStatus {
+    UNKNOWN = 0,
+    SUCCESS = 1,
+    UNSUPPORTED_CODEC_CONFIGURATION = 2,
+    // General failure
+    FAILURE = 3,
+    RECONFIGURATION = 4,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/BroadcastCapability.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/BroadcastCapability.aidl
new file mode 100644
index 0000000..f1301fb
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/BroadcastCapability.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.AudioLocation;
+import android.hardware.bluetooth.audio.CodecType;
+import android.hardware.bluetooth.audio.Lc3Capabilities;
+
+/**
+ * Used to specify the le audio broadcast codec capabilities for hardware offload.
+ */
+@VintfStability
+parcelable BroadcastCapability {
+    @VintfStability
+    parcelable VendorCapabilities {
+        ParcelableHolder extension;
+    }
+    @VintfStability
+    union LeAudioCodecCapabilities {
+        @nullable Lc3Capabilities[] lc3Capabilities;
+        @nullable VendorCapabilities[] vendorCapabillities;
+    }
+    CodecType codecType;
+    AudioLocation supportedChannel;
+    // Supported channel count for each stream
+    int channelCountPerStream;
+    LeAudioCodecCapabilities leAudioCodecCapabilities;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/ChannelMode.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/ChannelMode.aidl
new file mode 100644
index 0000000..6613872
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/ChannelMode.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+@VintfStability
+@Backing(type="byte")
+enum ChannelMode {
+    UNKNOWN,
+    MONO,
+    STEREO,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecCapabilities.aidl
new file mode 100644
index 0000000..9fcdf1c
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecCapabilities.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.AacCapabilities;
+import android.hardware.bluetooth.audio.AptxCapabilities;
+import android.hardware.bluetooth.audio.AptxAdaptiveCapabilities;
+import android.hardware.bluetooth.audio.CodecType;
+import android.hardware.bluetooth.audio.Lc3Capabilities;
+import android.hardware.bluetooth.audio.LdacCapabilities;
+import android.hardware.bluetooth.audio.SbcCapabilities;
+
+/**
+ * Used to specify the capabilities of the codecs supported by Hardware Encoding.
+ * AptX and AptX-HD both use the AptxCapabilities field.
+ */
+@VintfStability
+parcelable CodecCapabilities {
+    @VintfStability
+    parcelable VendorCapabilities {
+        ParcelableHolder extension;
+    }
+    @VintfStability
+    union Capabilities {
+        SbcCapabilities sbcCapabilities;
+        AacCapabilities aacCapabilities;
+        LdacCapabilities ldacCapabilities;
+        AptxCapabilities aptxCapabilities;
+        AptxAdaptiveCapabilities aptxAdaptiveCapabilities;
+        Lc3Capabilities lc3Capabilities;
+        VendorCapabilities vendorCapabilities;
+    }
+    CodecType codecType;
+    Capabilities capabilities;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecConfiguration.aidl
new file mode 100644
index 0000000..5ed12e3
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecConfiguration.aidl
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.AacConfiguration;
+import android.hardware.bluetooth.audio.AptxConfiguration;
+import android.hardware.bluetooth.audio.AptxAdaptiveConfiguration;
+import android.hardware.bluetooth.audio.CodecType;
+import android.hardware.bluetooth.audio.Lc3Configuration;
+import android.hardware.bluetooth.audio.LdacConfiguration;
+import android.hardware.bluetooth.audio.SbcConfiguration;
+
+/**
+ * Used to configure a Hardware Encoding session.
+ * AptX and AptX-HD both use the AptxConfiguration field.
+ */
+@VintfStability
+parcelable CodecConfiguration {
+    @VintfStability
+    parcelable VendorConfiguration {
+        int vendorId;
+        char codecId;
+        ParcelableHolder codecConfig;
+    }
+    @VintfStability
+    union CodecSpecific {
+        SbcConfiguration sbcConfig;
+        AacConfiguration aacConfig;
+        LdacConfiguration ldacConfig;
+        AptxConfiguration aptxConfig;
+        AptxAdaptiveConfiguration aptxAdaptiveConfig;
+        Lc3Configuration lc3Config;
+        VendorConfiguration vendorConfig;
+    }
+    CodecType codecType;
+    /**
+     * The encoded audio bitrate in bits / second.
+     * 0x00000000 - The audio bitrate is not specified / unused
+     * 0x00000001 - 0x00FFFFFF - Encoded audio bitrate in bits/second
+     * 0x01000000 - 0xFFFFFFFF - Reserved
+     *
+     * The HAL needs to support all legal bitrates for the selected codec.
+     */
+    int encodedAudioBitrate;
+    /**
+     * Peer MTU (in two-octets)
+     */
+    int peerMtu;
+    /**
+     * Content protection by SCMS-T
+     */
+    boolean isScmstEnabled;
+    CodecSpecific config;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecType.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecType.aidl
new file mode 100644
index 0000000..386876e
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/CodecType.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+@VintfStability
+@Backing(type="int")
+enum CodecType {
+    UNKNOWN,
+    SBC,
+    AAC,
+    APTX,
+    APTX_HD,
+    LDAC,
+    LC3,
+    VENDOR,
+    APTX_ADAPTIVE,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl
new file mode 100644
index 0000000..4ddf645
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.audio.common.SinkMetadata;
+import android.hardware.audio.common.SourceMetadata;
+import android.hardware.bluetooth.audio.CodecType;
+import android.hardware.bluetooth.audio.LatencyMode;
+import android.hardware.bluetooth.audio.PresentationPosition;
+
+/**
+ * HAL interface from the Audio HAL to the Bluetooth stack
+ *
+ * The Audio HAL calls methods in this interface to start, suspend, and stop
+ * an audio stream. These calls return immediately and the results, if any,
+ * are sent over the IBluetoothAudioProvider interface.
+ *
+ * Moreover, the Audio HAL can also get the presentation position of the stream
+ * and provide stream metadata.
+ *
+ */
+@VintfStability
+interface IBluetoothAudioPort {
+    /**
+     * Get the audio presentation position.
+     *
+     * @return the audio presentation position
+     *
+     */
+    PresentationPosition getPresentationPosition();
+
+    /**
+     * This indicates that the caller of this method has opened the data path
+     * and wants to start an audio stream. The caller must wait for a
+     * IBluetoothAudioProvider.streamStarted(Status) call.
+     *
+     * @param isLowLatency true if the stream being started with the latency
+     * control mechanism.
+     */
+    void startStream(boolean isLowLatency);
+
+    /**
+     * This indicates that the caller of this method wants to stop the audio
+     * stream. The data path will be closed after this call. There is no
+     * callback from the IBluetoothAudioProvider interface even though the
+     * teardown is asynchronous.
+     */
+    void stopStream();
+
+    /**
+     * This indicates that the caller of this method wants to suspend the audio
+     * stream. The caller must wait for the Bluetooth process to call
+     * IBluetoothAudioProvider.streamSuspended(Status). The caller still keeps
+     * the data path open.
+     */
+    void suspendStream();
+
+    /**
+     * Called when the metadata of the stream's source has been changed.
+     *
+     * @param sourceMetadata Description of the audio that is played by the
+     *    clients.
+     */
+    void updateSourceMetadata(in SourceMetadata sourceMetadata);
+
+    /**
+     * Called when the metadata of the stream's sink has been changed.
+     *
+     * @param sinkMetadata as passed from Audio Framework
+     */
+    void updateSinkMetadata(in SinkMetadata sinkMetadata);
+
+    /**
+     * Called when latency mode is changed.
+     *
+     * @param latencyMode latency mode from audio
+     */
+    void setLatencyMode(in LatencyMode latencyMode);
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl
new file mode 100644
index 0000000..d5c051e
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.AudioConfiguration;
+import android.hardware.bluetooth.audio.BluetoothAudioStatus;
+import android.hardware.bluetooth.audio.IBluetoothAudioPort;
+import android.hardware.bluetooth.audio.LatencyMode;
+import android.hardware.common.fmq.MQDescriptor;
+import android.hardware.common.fmq.SynchronizedReadWrite;
+
+/**
+ * HAL interface from the Bluetooth stack to the Audio HAL
+ *
+ * The Bluetooth stack calls methods in this interface to start and end audio
+ * sessions and sends callback events to the Audio HAL.
+ *
+ */
+@VintfStability
+interface IBluetoothAudioProvider {
+    /**
+     * Ends the current session and unregisters the IBluetoothAudioPort
+     * interface.
+     */
+    void endSession();
+
+    /**
+     * This method indicates that the Bluetooth stack is ready to stream audio.
+     * It registers an instance of IBluetoothAudioPort with and provides the
+     * current negotiated codec to the Audio HAL. After this method is called,
+     * the Audio HAL can invoke IBluetoothAudioPort.startStream().
+     *
+     * Note: endSession() must be called to unregister this IBluetoothAudioPort
+     *
+     * @param hostIf An instance of IBluetoothAudioPort for stream control
+     * @param audioConfig The audio configuration negotiated with the remote
+     *    device. The PCM parameters are set if software based encoding,
+     *    otherwise the correct codec configuration is used for hardware
+     *    encoding.
+     * @param supportedLatencyModes latency modes supported by the active
+     * remote device
+     *
+     * @return The fast message queue for audio data from/to this
+     *    provider. Audio data will be in PCM format as specified by the
+     *    audioConfig.pcmConfig parameter. Invalid if streaming is offloaded
+     *    from/to hardware or on failure
+     */
+    MQDescriptor<byte, SynchronizedReadWrite> startSession(
+            in IBluetoothAudioPort hostIf, in AudioConfiguration audioConfig,
+            in LatencyMode[] supportedLatencyModes);
+    /**
+     * Callback for IBluetoothAudioPort.startStream()
+     *
+     * @param status true for SUCCESS or false for FAILURE
+     */
+    void streamStarted(in BluetoothAudioStatus status);
+
+    /**
+     * Callback for IBluetoothAudioPort.suspendStream()
+     *
+     * @param status true for SUCCESS or false for FAILURE
+     */
+    void streamSuspended(in BluetoothAudioStatus status);
+
+    /**
+     * Called when the audio configuration of the stream has been changed.
+     *
+     * @param audioConfig The audio configuration negotiated with the remote
+     *    device. The PCM parameters are set if software based encoding,
+     *    otherwise the correct codec configuration is used for hardware
+     *    encoding.
+     */
+    void updateAudioConfiguration(in AudioConfiguration audioConfig);
+
+    /**
+     * Called when the supported latency mode is updated.
+     *
+     * @param allowed If the peripheral devices can't keep up with low latency
+     * mode, the API will be called with supported is false.
+     */
+    void setLowLatencyModeAllowed(in boolean allowed);
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.aidl
new file mode 100644
index 0000000..3cde22c
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.aidl
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.AudioCapabilities;
+import android.hardware.bluetooth.audio.IBluetoothAudioProvider;
+import android.hardware.bluetooth.audio.SessionType;
+/**
+ * This factory allows a HAL implementation to be split into multiple
+ * independent providers.
+ *
+ * When the Bluetooth stack is ready to create an audio session, it must first
+ * obtain the IBluetoothAudioProvider for that session type by calling
+ * openProvider().
+ *
+ */
+
+@VintfStability
+interface IBluetoothAudioProviderFactory {
+    /**
+     * Gets a list of audio capabilities for a session type.
+     *
+     * For software encoding, the PCM capabilities are returned.
+     * For hardware encoding, the supported codecs and their capabilities are
+     * returned.
+     *
+     * @param sessionType The session type (e.g.
+     *    A2DP_SOFTWARE_ENCODING_DATAPATH).
+     * @return A list containing all the capabilities
+     *    supported by the sesson type. The capabilities is a list of
+     *    available options when configuring the codec for the session.
+     *    For software encoding it is the PCM data rate.
+     *    For hardware encoding it is the list of supported codecs and their
+     *    capabilities.
+     *    If a provider isn't supported, an empty list should be returned.
+     *    Note: Only one entry should exist per codec when using hardware
+     *    encoding.
+     */
+    AudioCapabilities[] getProviderCapabilities(in SessionType sessionType);
+
+    /**
+     * Opens an audio provider for a session type. To close the provider, it is
+     * necessary to release references to the returned provider object.
+     *
+     * @param sessionType The session type (e.g.
+     *    LE_AUDIO_SOFTWARE_ENCODING_DATAPATH).
+     *
+     * @return provider The provider of the specified session type
+     */
+    IBluetoothAudioProvider openProvider(in SessionType sessionType);
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LatencyMode.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LatencyMode.aidl
new file mode 100644
index 0000000..0c354f7
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LatencyMode.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+@VintfStability
+@Backing(type="int")
+enum LatencyMode {
+    UNKNOWN,
+    LOW_LATENCY,
+    FREE,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/Lc3Capabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/Lc3Capabilities.aidl
new file mode 100644
index 0000000..fc2f382
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/Lc3Capabilities.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.ChannelMode;
+
+/**
+ * Used for Hardware Encoding/Decoding LC3 codec capabilities.
+ */
+@VintfStability
+parcelable Lc3Capabilities {
+    /*
+     * PCM is Input for encoder, Output for decoder
+     */
+    byte[] pcmBitDepth;
+    /*
+     * codec-specific parameters
+     */
+    int[] samplingFrequencyHz;
+    /*
+     * FrameDuration based on microseconds.
+     */
+    int[] frameDurationUs;
+    /*
+     * length in octets of a codec frame
+     */
+    int[] octetsPerFrame;
+    /*
+     * Number of blocks of codec frames per single SDU (Service Data Unit)
+     */
+    byte[] blocksPerSdu;
+    /*
+     * Channel mode used in A2DP special audio, ignored in standard LE Audio mode
+     */
+    ChannelMode[] channelMode;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/Lc3Configuration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/Lc3Configuration.aidl
new file mode 100644
index 0000000..e8a93b2
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/Lc3Configuration.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.ChannelMode;
+
+/**
+ * Used for Hardware Encoding/Decoding LC3 codec configuration.
+ */
+@VintfStability
+parcelable Lc3Configuration {
+    /*
+     * PCM is Input for encoder, Output for decoder
+     */
+    byte pcmBitDepth;
+    /*
+     * codec-specific parameters
+     */
+    int samplingFrequencyHz;
+    /*
+     * FrameDuration based on microseconds.
+     */
+    int frameDurationUs;
+    /*
+     * length in octets of a codec frame
+     */
+    int octetsPerFrame;
+    /*
+     * Number of blocks of codec frames per single SDU (Service Data Unit)
+     */
+    byte blocksPerSdu;
+    /*
+     * Channel mode used in A2DP special audio, ignored in standard LE Audio mode
+     */
+    ChannelMode channelMode;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacCapabilities.aidl
new file mode 100644
index 0000000..1dbec08
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacCapabilities.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.LdacChannelMode;
+import android.hardware.bluetooth.audio.LdacQualityIndex;
+
+/**
+ * Used for Hardware Encoding LDAC codec capabilities
+ * all qualities must be supported.
+ */
+@VintfStability
+parcelable LdacCapabilities {
+    int[] sampleRateHz;
+    LdacChannelMode[] channelMode;
+    LdacQualityIndex[] qualityIndex;
+    byte[] bitsPerSample;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacChannelMode.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacChannelMode.aidl
new file mode 100644
index 0000000..3cc910f
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacChannelMode.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+/**
+ * Channel Mode: 3 bits
+ */
+@VintfStability
+@Backing(type="byte")
+enum LdacChannelMode {
+    UNKNOWN,
+    STEREO,
+    DUAL,
+    MONO,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacConfiguration.aidl
new file mode 100644
index 0000000..cc03dd0
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacConfiguration.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.LdacChannelMode;
+import android.hardware.bluetooth.audio.LdacQualityIndex;
+
+/**
+ * Used for Hardware Encoding LDAC codec configuration
+ * Only used when configuring the codec.
+ */
+@VintfStability
+parcelable LdacConfiguration {
+    int sampleRateHz;
+    LdacChannelMode channelMode;
+    LdacQualityIndex qualityIndex;
+    byte bitsPerSample;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacQualityIndex.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacQualityIndex.aidl
new file mode 100644
index 0000000..9993b8b
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LdacQualityIndex.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+@VintfStability
+@Backing(type="byte")
+enum LdacQualityIndex {
+    /**
+     * 990kbps
+     */
+    HIGH,
+    /**
+     * 660kbps
+     */
+    MID,
+    /**
+     * 330kbps
+     */
+    LOW,
+    /**
+     * Adaptive Bit Rate mode
+     */
+    ABR,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioBroadcastConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioBroadcastConfiguration.aidl
new file mode 100644
index 0000000..e9a1a0c
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioBroadcastConfiguration.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.CodecType;
+import android.hardware.bluetooth.audio.LeAudioCodecConfiguration;
+
+@VintfStability
+parcelable LeAudioBroadcastConfiguration {
+    @VintfStability
+    parcelable BroadcastStreamMap {
+        /*
+         * The connection handle used for a broadcast group.
+         * Range: 0x0000 to 0xEFFF
+         */
+        char streamHandle;
+        /*
+         * Audio channel allocation is  a bit field, each enabled bit means that given audio
+         * direction, i.e. "left", or "right" is used. Ordering of audio channels comes from the
+         * least significant bit to the most significant bit.
+         */
+        int audioChannelAllocation;
+        LeAudioCodecConfiguration leAudioCodecConfig;
+    }
+    CodecType codecType;
+    BroadcastStreamMap[] streamMap;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioCodecCapabilitiesSetting.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioCodecCapabilitiesSetting.aidl
new file mode 100644
index 0000000..58dac06
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioCodecCapabilitiesSetting.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.BroadcastCapability;
+import android.hardware.bluetooth.audio.UnicastCapability;
+
+/**
+ * Used to specify the le audio capabilities for unicast and broadcast hardware offload.
+ */
+@VintfStability
+parcelable LeAudioCodecCapabilitiesSetting {
+    UnicastCapability unicastEncodeCapability;
+    UnicastCapability unicastDecodeCapability;
+    BroadcastCapability broadcastCapability;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioCodecConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioCodecConfiguration.aidl
new file mode 100644
index 0000000..421eeb2
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioCodecConfiguration.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.Lc3Configuration;
+
+@VintfStability
+union LeAudioCodecConfiguration {
+    @VintfStability
+    parcelable VendorConfiguration {
+        ParcelableHolder extension;
+    }
+    Lc3Configuration lc3Config;
+    VendorConfiguration vendorConfig;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioConfiguration.aidl
new file mode 100644
index 0000000..0d1e3de
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/LeAudioConfiguration.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.CodecType;
+import android.hardware.bluetooth.audio.LeAudioCodecConfiguration;
+
+@VintfStability
+parcelable LeAudioConfiguration {
+    @VintfStability
+    parcelable StreamMap {
+        /*
+         * The connection handle used for a unicast group.
+         * Range: 0x0000 to 0xEFFF
+         */
+        char streamHandle;
+        /*
+         * Audio channel allocation is  a bit field, each enabled bit means that given audio
+         * direction, i.e. "left", or "right" is used. Ordering of audio channels comes from the
+         * least significant bit to the most significant bit. The valus follows the Bluetooth SIG
+         * Audio Location assigned number.
+         */
+        int audioChannelAllocation;
+    }
+    CodecType codecType;
+    StreamMap[] streamMap;
+    int peerDelayUs;
+    LeAudioCodecConfiguration leAudioCodecConfig;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/PcmCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/PcmCapabilities.aidl
new file mode 100644
index 0000000..776b777
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/PcmCapabilities.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.ChannelMode;
+
+/**
+ * Used for Software Encoding audio feed capabilities
+ */
+@VintfStability
+parcelable PcmCapabilities {
+    int[] sampleRateHz;
+    ChannelMode[] channelMode;
+    byte[] bitsPerSample;
+    /**
+     * Data interval for data transfer
+     */
+    int[] dataIntervalUs;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/PcmConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/PcmConfiguration.aidl
new file mode 100644
index 0000000..03aa27b
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/PcmConfiguration.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.ChannelMode;
+
+/**
+ * Used for Software Encoding audio feed configuration
+ */
+@VintfStability
+parcelable PcmConfiguration {
+    int sampleRateHz;
+    ChannelMode channelMode;
+    byte bitsPerSample;
+    /**
+     * Data interval for data transfer
+     */
+    int dataIntervalUs;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/PresentationPosition.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/PresentationPosition.aidl
new file mode 100644
index 0000000..f3b8aed
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/PresentationPosition.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+@VintfStability
+parcelable PresentationPosition {
+    @VintfStability
+    parcelable TimeSpec {
+        /**
+         * seconds
+         */
+        long tvSec;
+        /**
+         *  nanoseconds
+         */
+        long tvNSec;
+    }
+    /*
+     * remoteDeviceAudioDelayNanos the audio delay from when the remote
+     * device (e.g. headset) receives audio data to when the device plays the
+     * sound. If the delay is unknown, the value is set to zero.
+     */
+    long remoteDeviceAudioDelayNanos;
+    /*
+     * transmittedOctets the number of audio data octets that were sent
+     * to a remote device. This excludes octets that have been written to the
+     * data path but have not been sent to the remote device. The count is
+     * not reset until stopStream() is called. If the software data path is
+     * unused (e.g. Hardware Offload), the value is set to 0.
+     */
+    long transmittedOctets;
+    /*
+     * transmittedOctetsTimestamp the value of CLOCK_MONOTONIC
+     * corresponding to transmittedOctets. If the software data path is
+     * unused (e.g., for Hardware Offload), the value is set to zero.
+     */
+    TimeSpec transmittedOctetsTimestamp;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcAllocMethod.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcAllocMethod.aidl
new file mode 100644
index 0000000..1159f30
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcAllocMethod.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+@VintfStability
+@Backing(type="byte")
+enum SbcAllocMethod {
+    /**
+     * SNR
+     */
+    ALLOC_MD_S,
+    /**
+     * Loudness
+     */
+    ALLOC_MD_L,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcCapabilities.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcCapabilities.aidl
new file mode 100644
index 0000000..743a1f7
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcCapabilities.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.SbcAllocMethod;
+import android.hardware.bluetooth.audio.SbcChannelMode;
+
+/**
+ * Used for Hardware Encoding SBC codec capabilities.
+ */
+@VintfStability
+parcelable SbcCapabilities {
+    int[] sampleRateHz;
+    SbcChannelMode[] channelMode;
+    byte[] blockLength;
+    byte[] numSubbands;
+    SbcAllocMethod[] allocMethod;
+    byte[] bitsPerSample;
+    /*
+     * range from 2 to 250.
+     */
+    int minBitpool;
+    /*
+     * range from 2 to 250.
+     */
+    int maxBitpool;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcChannelMode.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcChannelMode.aidl
new file mode 100644
index 0000000..68e3267
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcChannelMode.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+@VintfStability
+@Backing(type="byte")
+enum SbcChannelMode {
+    UNKNOWN,
+    JOINT_STEREO,
+    STEREO,
+    DUAL,
+    MONO,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcConfiguration.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcConfiguration.aidl
new file mode 100644
index 0000000..054d03e
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SbcConfiguration.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.SbcAllocMethod;
+import android.hardware.bluetooth.audio.SbcChannelMode;
+
+/**
+ * Used for Hardware Encoding SBC codec configuration.
+ */
+@VintfStability
+parcelable SbcConfiguration {
+    int sampleRateHz;
+    SbcChannelMode channelMode;
+    byte blockLength;
+    byte numSubbands;
+    SbcAllocMethod allocMethod;
+    byte bitsPerSample;
+    /*
+     * range from 2 to 250.
+     */
+    int minBitpool;
+    /*
+     * range from 2 to 250.
+     */
+    int maxBitpool;
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SessionType.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SessionType.aidl
new file mode 100644
index 0000000..7acb5c6
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/SessionType.aidl
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+@VintfStability
+@Backing(type="byte")
+enum SessionType {
+    UNKNOWN,
+    /**
+     * A2DP legacy that AVDTP media is encoded by Bluetooth Stack
+     */
+    A2DP_SOFTWARE_ENCODING_DATAPATH,
+    /**
+     * The encoding of AVDTP media is done by HW and there is control only
+     */
+    A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
+    /**
+     * Used when encoded by Bluetooth Stack and streaming to Hearing Aid
+     */
+    HEARING_AID_SOFTWARE_ENCODING_DATAPATH,
+    /**
+     * Used when audio is encoded by the Bluetooth Stack and is streamed to LE
+     * Audio unicast device.
+     */
+    LE_AUDIO_SOFTWARE_ENCODING_DATAPATH,
+    /**
+     * Used when audio is decoded by the Bluetooth Stack and is streamed to LE
+     * Audio unicast device.
+     */
+    LE_AUDIO_SOFTWARE_DECODING_DATAPATH,
+    /**
+     * Used when audio is encoded by hardware offload and is streamed to LE
+     * Audio unicast device. This is a control path only.
+     */
+    LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
+    /**
+     * Used when audio is decoded by hardware offload and is streamed to LE
+     * Audio unicast device. This is a control path only.
+     */
+    LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH,
+    /**
+     * Used when audio is encoded by the Bluetooth stack and is streamed to LE
+     * Audio broadcast channels.
+     */
+    LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH,
+    /**
+     * Used when audio is encoded by hardware offload and is streamed to LE
+     * Audio broadcast channels. This is a control path only.
+     */
+    LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
+    /**
+     * A2DP legacy that AVDTP media is decoded by Bluetooth Stack
+     */
+    A2DP_SOFTWARE_DECODING_DATAPATH,
+    /**
+     * The decoding of AVDTP media is done by HW and there is control only
+     */
+    A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH,
+}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/UnicastCapability.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/UnicastCapability.aidl
new file mode 100644
index 0000000..f8a924a
--- /dev/null
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/UnicastCapability.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio;
+
+import android.hardware.bluetooth.audio.AudioLocation;
+import android.hardware.bluetooth.audio.CodecType;
+import android.hardware.bluetooth.audio.Lc3Capabilities;
+
+/**
+ * Used to specify the le audio unicast codec capabilities for hardware offload.
+ */
+@VintfStability
+parcelable UnicastCapability {
+    @VintfStability
+    parcelable VendorCapabilities {
+        ParcelableHolder extension;
+    }
+    @VintfStability
+    union LeAudioCodecCapabilities {
+        Lc3Capabilities lc3Capabilities;
+        VendorCapabilities vendorCapabillities;
+    }
+    CodecType codecType;
+    AudioLocation supportedChannel;
+    // The number of connected device
+    int deviceCount;
+    // Supported channel count for each device
+    int channelCountPerDevice;
+    LeAudioCodecCapabilities leAudioCodecCapabilities;
+}
diff --git a/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.cpp b/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.cpp
new file mode 100644
index 0000000..2d0d8c9
--- /dev/null
+++ b/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.cpp
@@ -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.
+ */
+
+#define LOG_TAG "BTAudioProviderA2dpHW"
+
+#include "A2dpOffloadAudioProvider.h"
+
+#include <BluetoothAudioCodecs.h>
+#include <BluetoothAudioSessionReport.h>
+#include <android-base/logging.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+A2dpOffloadEncodingAudioProvider::A2dpOffloadEncodingAudioProvider()
+    : A2dpOffloadAudioProvider() {
+  session_type_ = SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
+}
+
+A2dpOffloadDecodingAudioProvider::A2dpOffloadDecodingAudioProvider()
+    : A2dpOffloadAudioProvider() {
+  session_type_ = SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH;
+}
+
+A2dpOffloadAudioProvider::A2dpOffloadAudioProvider() {}
+
+bool A2dpOffloadAudioProvider::isValid(const SessionType& session_type) {
+  return (session_type == session_type_);
+}
+
+ndk::ScopedAStatus A2dpOffloadAudioProvider::startSession(
+    const std::shared_ptr<IBluetoothAudioPort>& host_if,
+    const AudioConfiguration& audio_config,
+    const std::vector<LatencyMode>& latency_modes, DataMQDesc* _aidl_return) {
+  if (audio_config.getTag() != AudioConfiguration::a2dpConfig) {
+    LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
+                 << audio_config.toString();
+    *_aidl_return = DataMQDesc();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+  if (!BluetoothAudioCodecs::IsOffloadCodecConfigurationValid(
+          session_type_, audio_config.get<AudioConfiguration::a2dpConfig>())) {
+    LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
+                 << audio_config.toString();
+    *_aidl_return = DataMQDesc();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+  return BluetoothAudioProvider::startSession(
+      host_if, audio_config, latency_modes, _aidl_return);
+}
+
+ndk::ScopedAStatus A2dpOffloadAudioProvider::onSessionReady(
+    DataMQDesc* _aidl_return) {
+  *_aidl_return = DataMQDesc();
+  BluetoothAudioSessionReport::OnSessionStarted(
+      session_type_, stack_iface_, nullptr, *audio_config_, latency_modes_);
+  return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.h b/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.h
new file mode 100644
index 0000000..e6f188b
--- /dev/null
+++ b/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.h
@@ -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.
+ */
+
+#pragma once
+
+#include "BluetoothAudioProvider.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+class A2dpOffloadAudioProvider : public BluetoothAudioProvider {
+ public:
+  A2dpOffloadAudioProvider();
+
+  bool isValid(const SessionType& session_type) override;
+
+  ndk::ScopedAStatus startSession(
+      const std::shared_ptr<IBluetoothAudioPort>& host_if,
+      const AudioConfiguration& audio_config,
+      const std::vector<LatencyMode>& latency_modes,
+      DataMQDesc* _aidl_return);
+
+ private:
+  ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) override;
+};
+
+class A2dpOffloadEncodingAudioProvider : public A2dpOffloadAudioProvider {
+ public:
+  A2dpOffloadEncodingAudioProvider();
+};
+
+class A2dpOffloadDecodingAudioProvider : public A2dpOffloadAudioProvider {
+ public:
+  A2dpOffloadDecodingAudioProvider();
+};
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.cpp b/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.cpp
new file mode 100644
index 0000000..bd2da95
--- /dev/null
+++ b/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.cpp
@@ -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.
+ */
+
+#define LOG_TAG "BTAudioProviderA2dpSW"
+
+#include "A2dpSoftwareAudioProvider.h"
+
+#include <BluetoothAudioCodecs.h>
+#include <BluetoothAudioSessionReport.h>
+#include <android-base/logging.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+// Here the buffer size is based on SBC
+static constexpr uint32_t kPcmFrameSize = 4;  // 16 bits per sample / stereo
+// SBC is 128, and here we choose the LCM of 16, 24, and 32
+static constexpr uint32_t kPcmFrameCount = 96;
+static constexpr uint32_t kRtpFrameSize = kPcmFrameSize * kPcmFrameCount;
+// The max counts by 1 tick (20ms) for SBC is about 7. Since using 96 for the
+// PCM counts, here we just choose a greater number
+static constexpr uint32_t kRtpFrameCount = 10;
+static constexpr uint32_t kBufferSize = kRtpFrameSize * kRtpFrameCount;
+static constexpr uint32_t kBufferCount = 2;  // double buffer
+static constexpr uint32_t kDataMqSize = kBufferSize * kBufferCount;
+
+A2dpSoftwareEncodingAudioProvider::A2dpSoftwareEncodingAudioProvider()
+    : A2dpSoftwareAudioProvider() {
+  session_type_ = SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH;
+}
+
+A2dpSoftwareDecodingAudioProvider::A2dpSoftwareDecodingAudioProvider()
+    : A2dpSoftwareAudioProvider() {
+  session_type_ = SessionType::A2DP_SOFTWARE_DECODING_DATAPATH;
+}
+
+A2dpSoftwareAudioProvider::A2dpSoftwareAudioProvider()
+    : BluetoothAudioProvider(), data_mq_(nullptr) {
+  LOG(INFO) << __func__ << " - size of audio buffer " << kDataMqSize
+            << " byte(s)";
+  std::unique_ptr<DataMQ> data_mq(
+      new DataMQ(kDataMqSize, /* EventFlag */ true));
+  if (data_mq && data_mq->isValid()) {
+    data_mq_ = std::move(data_mq);
+  } else {
+    ALOGE_IF(!data_mq, "failed to allocate data MQ");
+    ALOGE_IF(data_mq && !data_mq->isValid(), "data MQ is invalid");
+  }
+}
+
+bool A2dpSoftwareAudioProvider::isValid(const SessionType& sessionType) {
+  return (sessionType == session_type_ && data_mq_ && data_mq_->isValid());
+}
+
+ndk::ScopedAStatus A2dpSoftwareAudioProvider::startSession(
+    const std::shared_ptr<IBluetoothAudioPort>& host_if,
+    const AudioConfiguration& audio_config,
+    const std::vector<LatencyMode>& latency_modes, DataMQDesc* _aidl_return) {
+  if (audio_config.getTag() != AudioConfiguration::pcmConfig) {
+    LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
+                 << audio_config.toString();
+    *_aidl_return = DataMQDesc();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+  const PcmConfiguration& pcm_config =
+      audio_config.get<AudioConfiguration::pcmConfig>();
+  if (!BluetoothAudioCodecs::IsSoftwarePcmConfigurationValid(pcm_config)) {
+    LOG(WARNING) << __func__ << " - Unsupported PCM Configuration="
+                 << pcm_config.toString();
+    *_aidl_return = DataMQDesc();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+
+  return BluetoothAudioProvider::startSession(
+      host_if, audio_config, latency_modes, _aidl_return);
+}
+
+ndk::ScopedAStatus A2dpSoftwareAudioProvider::onSessionReady(
+    DataMQDesc* _aidl_return) {
+  if (data_mq_ == nullptr || !data_mq_->isValid()) {
+    *_aidl_return = DataMQDesc();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+  *_aidl_return = data_mq_->dupeDesc();
+  auto desc = data_mq_->dupeDesc();
+  BluetoothAudioSessionReport::OnSessionStarted(
+      session_type_, stack_iface_, &desc, *audio_config_, latency_modes_);
+  return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.h b/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.h
new file mode 100644
index 0000000..3ebecf2
--- /dev/null
+++ b/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.h
@@ -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.
+ */
+
+#pragma once
+
+#include "BluetoothAudioProvider.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+class A2dpSoftwareAudioProvider : public BluetoothAudioProvider {
+ public:
+  A2dpSoftwareAudioProvider();
+
+  bool isValid(const SessionType& sessionType) override;
+
+  ndk::ScopedAStatus startSession(
+      const std::shared_ptr<IBluetoothAudioPort>& host_if,
+      const AudioConfiguration& audio_config,
+      const std::vector<LatencyMode>& latency_modes,
+      DataMQDesc* _aidl_return);
+
+ private:
+  // audio data queue for software encoding
+  std::unique_ptr<DataMQ> data_mq_;
+
+  ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) override;
+};
+
+class A2dpSoftwareEncodingAudioProvider : public A2dpSoftwareAudioProvider {
+ public:
+  A2dpSoftwareEncodingAudioProvider();
+};
+
+class A2dpSoftwareDecodingAudioProvider : public A2dpSoftwareAudioProvider {
+ public:
+  A2dpSoftwareDecodingAudioProvider();
+};
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/bluetooth/audio/aidl/default/Android.bp b/bluetooth/audio/aidl/default/Android.bp
new file mode 100644
index 0000000..13a5440
--- /dev/null
+++ b/bluetooth/audio/aidl/default/Android.bp
@@ -0,0 +1,35 @@
+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: "android.hardware.bluetooth.audio-impl",
+    vendor: true,
+    vintf_fragments: ["bluetooth_audio.xml"],
+    srcs: [
+        "BluetoothAudioProvider.cpp",
+        "BluetoothAudioProviderFactory.cpp",
+        "A2dpOffloadAudioProvider.cpp",
+        "A2dpSoftwareAudioProvider.cpp",
+        "HearingAidAudioProvider.cpp",
+        "LeAudioOffloadAudioProvider.cpp",
+        "LeAudioSoftwareAudioProvider.cpp",
+        "service.cpp",
+    ],
+    export_include_dirs: ["."],
+    header_libs: ["libhardware_headers"],
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "libcutils",
+        "libfmq",
+        "liblog",
+        "android.hardware.bluetooth.audio-V1-ndk",
+        "libbluetooth_audio_session_aidl",
+    ],
+}
diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp b/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp
new file mode 100644
index 0000000..2a88959
--- /dev/null
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "BTAudioProviderStub"
+
+#include "BluetoothAudioProvider.h"
+
+#include <BluetoothAudioSessionReport.h>
+#include <android-base/logging.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+BluetoothAudioProvider::BluetoothAudioProvider() {
+  death_recipient_ = ::ndk::ScopedAIBinder_DeathRecipient(
+      AIBinder_DeathRecipient_new(binderDiedCallbackAidl));
+}
+
+ndk::ScopedAStatus BluetoothAudioProvider::startSession(
+    const std::shared_ptr<IBluetoothAudioPort>& host_if,
+    const AudioConfiguration& audio_config,
+    const std::vector<LatencyMode>& latencyModes,
+    DataMQDesc* _aidl_return) {
+  if (host_if == nullptr) {
+    *_aidl_return = DataMQDesc();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+
+  latency_modes_ = latencyModes;
+  audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
+  stack_iface_ = host_if;
+  is_binder_died = false;
+
+  AIBinder_linkToDeath(stack_iface_->asBinder().get(), death_recipient_.get(),
+                       this);
+
+  onSessionReady(_aidl_return);
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus BluetoothAudioProvider::endSession() {
+  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
+
+  if (stack_iface_ != nullptr) {
+    BluetoothAudioSessionReport::OnSessionEnded(session_type_);
+
+    if (!is_binder_died) {
+      AIBinder_unlinkToDeath(stack_iface_->asBinder().get(),
+                             death_recipient_.get(), this);
+    }
+  } else {
+    LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+              << " has NO session";
+  }
+
+  stack_iface_ = nullptr;
+  audio_config_ = nullptr;
+
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus BluetoothAudioProvider::streamStarted(
+    BluetoothAudioStatus status) {
+  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+            << ", status=" << toString(status);
+
+  if (stack_iface_ != nullptr) {
+    BluetoothAudioSessionReport::ReportControlStatus(session_type_, true,
+                                                     status);
+  } else {
+    LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
+                 << ", status=" << toString(status) << " has NO session";
+  }
+
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus BluetoothAudioProvider::streamSuspended(
+    BluetoothAudioStatus status) {
+  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+            << ", status=" << toString(status);
+
+  if (stack_iface_ != nullptr) {
+    BluetoothAudioSessionReport::ReportControlStatus(session_type_, false,
+                                                     status);
+  } else {
+    LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
+                 << ", status=" << toString(status) << " has NO session";
+  }
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus BluetoothAudioProvider::updateAudioConfiguration(
+    const AudioConfiguration& audio_config) {
+  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
+
+  if (stack_iface_ == nullptr || audio_config_ == nullptr) {
+    LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+              << " has NO session";
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+
+  if (audio_config.getTag() != audio_config_->getTag()) {
+    LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+              << " audio config type is not match";
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+
+  audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
+  BluetoothAudioSessionReport::ReportAudioConfigChanged(session_type_,
+                                                        *audio_config_);
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus BluetoothAudioProvider::setLowLatencyModeAllowed(
+    bool allowed) {
+  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
+
+  if (stack_iface_ == nullptr) {
+    LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+              << " has NO session";
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+  LOG(INFO) << __func__ << " - allowed " << allowed;
+  BluetoothAudioSessionReport::ReportLowLatencyModeAllowedChanged(
+    session_type_, allowed);
+  return ndk::ScopedAStatus::ok();
+}
+
+void BluetoothAudioProvider::binderDiedCallbackAidl(void* ptr) {
+  LOG(ERROR) << __func__ << " - BluetoothAudio Service died";
+  auto provider = static_cast<BluetoothAudioProvider*>(ptr);
+  if (provider == nullptr) {
+    LOG(ERROR) << __func__ << ": Null AudioProvider HAL died";
+    return;
+  }
+  provider->is_binder_died = true;
+  provider->endSession();
+}
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
\ No newline at end of file
diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProvider.h b/bluetooth/audio/aidl/default/BluetoothAudioProvider.h
new file mode 100644
index 0000000..dbfff7d
--- /dev/null
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProvider.h
@@ -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.
+ */
+#pragma once
+
+#include <aidl/android/hardware/bluetooth/audio/BnBluetoothAudioProvider.h>
+#include <aidl/android/hardware/bluetooth/audio/LatencyMode.h>
+#include <aidl/android/hardware/bluetooth/audio/SessionType.h>
+#include <fmq/AidlMessageQueue.h>
+
+using ::aidl::android::hardware::common::fmq::MQDescriptor;
+using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using ::android::AidlMessageQueue;
+
+using MqDataType = int8_t;
+using MqDataMode = SynchronizedReadWrite;
+using DataMQ = AidlMessageQueue<MqDataType, MqDataMode>;
+using DataMQDesc = MQDescriptor<MqDataType, MqDataMode>;
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+class BluetoothAudioProvider : public BnBluetoothAudioProvider {
+ public:
+  BluetoothAudioProvider();
+  ndk::ScopedAStatus startSession(
+      const std::shared_ptr<IBluetoothAudioPort>& host_if,
+      const AudioConfiguration& audio_config,
+      const std::vector<LatencyMode>& latency_modes,
+      DataMQDesc* _aidl_return);
+  ndk::ScopedAStatus endSession();
+  ndk::ScopedAStatus streamStarted(BluetoothAudioStatus status);
+  ndk::ScopedAStatus streamSuspended(BluetoothAudioStatus status);
+  ndk::ScopedAStatus updateAudioConfiguration(
+      const AudioConfiguration& audio_config);
+  ndk::ScopedAStatus setLowLatencyModeAllowed(bool allowed);
+
+  virtual bool isValid(const SessionType& sessionType) = 0;
+
+ protected:
+  virtual ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) = 0;
+  static void binderDiedCallbackAidl(void* cookie_ptr);
+
+  ::ndk::ScopedAIBinder_DeathRecipient death_recipient_;
+
+  std::shared_ptr<IBluetoothAudioPort> stack_iface_;
+  std::unique_ptr<AudioConfiguration> audio_config_ = nullptr;
+  SessionType session_type_;
+  std::vector<LatencyMode> latency_modes_;
+  bool is_binder_died = false;
+};
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp
new file mode 100644
index 0000000..91731d4
--- /dev/null
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "BTAudioProviderFactoryAIDL"
+
+#include "BluetoothAudioProviderFactory.h"
+
+#include <BluetoothAudioCodecs.h>
+#include <android-base/logging.h>
+
+#include "A2dpOffloadAudioProvider.h"
+#include "A2dpSoftwareAudioProvider.h"
+#include "BluetoothAudioProvider.h"
+#include "HearingAidAudioProvider.h"
+#include "LeAudioOffloadAudioProvider.h"
+#include "LeAudioSoftwareAudioProvider.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+BluetoothAudioProviderFactory::BluetoothAudioProviderFactory() {}
+
+ndk::ScopedAStatus BluetoothAudioProviderFactory::openProvider(
+    const SessionType session_type,
+    std::shared_ptr<IBluetoothAudioProvider>* _aidl_return) {
+  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type);
+  std::shared_ptr<BluetoothAudioProvider> provider = nullptr;
+
+  switch (session_type) {
+    case SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH:
+      provider = ndk::SharedRefBase::make<A2dpSoftwareEncodingAudioProvider>();
+      break;
+    case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
+      provider = ndk::SharedRefBase::make<A2dpOffloadEncodingAudioProvider>();
+      break;
+    case SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH:
+      provider = ndk::SharedRefBase::make<HearingAidAudioProvider>();
+      break;
+    case SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH:
+      provider = ndk::SharedRefBase::make<LeAudioSoftwareOutputAudioProvider>();
+      break;
+    case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
+      provider = ndk::SharedRefBase::make<LeAudioOffloadOutputAudioProvider>();
+      break;
+    case SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH:
+      provider = ndk::SharedRefBase::make<LeAudioSoftwareInputAudioProvider>();
+      break;
+    case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
+      provider = ndk::SharedRefBase::make<LeAudioOffloadInputAudioProvider>();
+      break;
+    case SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH:
+      provider =
+          ndk::SharedRefBase::make<LeAudioSoftwareBroadcastAudioProvider>();
+      break;
+    case SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
+      provider =
+          ndk::SharedRefBase::make<LeAudioOffloadBroadcastAudioProvider>();
+      break;
+    case SessionType::A2DP_SOFTWARE_DECODING_DATAPATH:
+      provider = ndk::SharedRefBase::make<A2dpSoftwareDecodingAudioProvider>();
+      break;
+    case SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH:
+      provider = ndk::SharedRefBase::make<A2dpOffloadDecodingAudioProvider>();
+      break;
+    default:
+      provider = nullptr;
+      break;
+  }
+
+  if (provider == nullptr || !provider->isValid(session_type)) {
+    provider = nullptr;
+    LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type);
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+  *_aidl_return = provider;
+
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus BluetoothAudioProviderFactory::getProviderCapabilities(
+    const SessionType session_type,
+    std::vector<AudioCapabilities>* _aidl_return) {
+  if (session_type == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+      session_type == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+    auto codec_capabilities =
+        BluetoothAudioCodecs::GetA2dpOffloadCodecCapabilities(session_type);
+    _aidl_return->resize(codec_capabilities.size());
+    for (int i = 0; i < codec_capabilities.size(); i++) {
+      _aidl_return->at(i).set<AudioCapabilities::a2dpCapabilities>(
+          codec_capabilities[i]);
+    }
+  } else if (session_type ==
+                 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+             session_type ==
+                 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
+             session_type ==
+                 SessionType::
+                     LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
+    std::vector<LeAudioCodecCapabilitiesSetting> db_codec_capabilities =
+        BluetoothAudioCodecs::GetLeAudioOffloadCodecCapabilities(session_type);
+    if (db_codec_capabilities.size()) {
+      _aidl_return->resize(db_codec_capabilities.size());
+      for (int i = 0; i < db_codec_capabilities.size(); ++i) {
+        _aidl_return->at(i).set<AudioCapabilities::leAudioCapabilities>(
+            db_codec_capabilities[i]);
+      }
+    }
+  } else if (session_type != SessionType::UNKNOWN) {
+    auto pcm_capabilities = BluetoothAudioCodecs::GetSoftwarePcmCapabilities();
+    _aidl_return->resize(pcm_capabilities.size());
+    for (int i = 0; i < pcm_capabilities.size(); i++) {
+      _aidl_return->at(i).set<AudioCapabilities::pcmCapabilities>(
+          pcm_capabilities[i]);
+    }
+  }
+
+  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type)
+            << " supports " << _aidl_return->size() << " codecs";
+  return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
\ No newline at end of file
diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.h b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.h
new file mode 100644
index 0000000..b38cfd2
--- /dev/null
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.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 <aidl/android/hardware/bluetooth/audio/BnBluetoothAudioProviderFactory.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+class BluetoothAudioProviderFactory : public BnBluetoothAudioProviderFactory {
+ public:
+  BluetoothAudioProviderFactory();
+
+  ndk::ScopedAStatus openProvider(
+      const SessionType session_type,
+      std::shared_ptr<IBluetoothAudioProvider>* _aidl_return) override;
+
+  ndk::ScopedAStatus getProviderCapabilities(
+      const SessionType session_type,
+      std::vector<AudioCapabilities>* _aidl_return) override;
+};
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/bluetooth/audio/aidl/default/HearingAidAudioProvider.cpp b/bluetooth/audio/aidl/default/HearingAidAudioProvider.cpp
new file mode 100644
index 0000000..e8b01ac
--- /dev/null
+++ b/bluetooth/audio/aidl/default/HearingAidAudioProvider.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "BTAudioProviderHearingAid"
+
+#include "HearingAidAudioProvider.h"
+
+#include <BluetoothAudioCodecs.h>
+#include <BluetoothAudioSessionReport.h>
+#include <android-base/logging.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+static constexpr uint32_t kPcmFrameSize = 4;  // 16 bits per sample / stereo
+static constexpr uint32_t kPcmFrameCount = 128;
+static constexpr uint32_t kRtpFrameSize = kPcmFrameSize * kPcmFrameCount;
+static constexpr uint32_t kRtpFrameCount = 7;  // max counts by 1 tick (20ms)
+static constexpr uint32_t kBufferSize = kRtpFrameSize * kRtpFrameCount;
+static constexpr uint32_t kBufferCount = 1;  // single buffer
+static constexpr uint32_t kDataMqSize = kBufferSize * kBufferCount;
+
+HearingAidAudioProvider::HearingAidAudioProvider()
+    : BluetoothAudioProvider(), data_mq_(nullptr) {
+  LOG(INFO) << __func__ << " - size of audio buffer " << kDataMqSize
+            << " byte(s)";
+  std::unique_ptr<DataMQ> data_mq(
+      new DataMQ(kDataMqSize, /* EventFlag */ true));
+  if (data_mq && data_mq->isValid()) {
+    data_mq_ = std::move(data_mq);
+    session_type_ = SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH;
+  } else {
+    ALOGE_IF(!data_mq, "failed to allocate data MQ");
+    ALOGE_IF(data_mq && !data_mq->isValid(), "data MQ is invalid");
+  }
+}
+bool HearingAidAudioProvider::isValid(const SessionType& sessionType) {
+  return (sessionType == session_type_ && data_mq_ && data_mq_->isValid());
+}
+
+ndk::ScopedAStatus HearingAidAudioProvider::startSession(
+    const std::shared_ptr<IBluetoothAudioPort>& host_if,
+    const AudioConfiguration& audio_config,
+    const std::vector<LatencyMode>& latency_modes, DataMQDesc* _aidl_return) {
+  if (audio_config.getTag() != AudioConfiguration::pcmConfig) {
+    LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
+                 << audio_config.toString();
+    *_aidl_return = DataMQDesc();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+  const auto& pcm_config = audio_config.get<AudioConfiguration::pcmConfig>();
+  if (!BluetoothAudioCodecs::IsSoftwarePcmConfigurationValid(pcm_config)) {
+    LOG(WARNING) << __func__ << " - Unsupported PCM Configuration="
+                 << pcm_config.toString();
+    *_aidl_return = DataMQDesc();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+
+  return BluetoothAudioProvider::startSession(
+      host_if, audio_config, latency_modes, _aidl_return);
+}
+
+ndk::ScopedAStatus HearingAidAudioProvider::onSessionReady(
+    DataMQDesc* _aidl_return) {
+  if (data_mq_ == nullptr || !data_mq_->isValid()) {
+    *_aidl_return = DataMQDesc();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+  *_aidl_return = data_mq_->dupeDesc();
+  auto desc = data_mq_->dupeDesc();
+  BluetoothAudioSessionReport::OnSessionStarted(
+      session_type_, stack_iface_, &desc, *audio_config_, latency_modes_);
+  return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/bluetooth/audio/aidl/default/HearingAidAudioProvider.h b/bluetooth/audio/aidl/default/HearingAidAudioProvider.h
new file mode 100644
index 0000000..a158c86
--- /dev/null
+++ b/bluetooth/audio/aidl/default/HearingAidAudioProvider.h
@@ -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.
+ */
+
+#pragma once
+
+#include "BluetoothAudioProvider.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+class HearingAidAudioProvider : public BluetoothAudioProvider {
+ public:
+  HearingAidAudioProvider();
+
+  bool isValid(const SessionType& sessionType) override;
+
+  ndk::ScopedAStatus startSession(
+      const std::shared_ptr<IBluetoothAudioPort>& host_if,
+      const AudioConfiguration& audio_config,
+      const std::vector<LatencyMode>& latency_modes,
+      DataMQDesc* _aidl_return);
+
+ private:
+  // audio data queue for software encoding
+  std::unique_ptr<DataMQ> data_mq_;
+
+  ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) override;
+};
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
new file mode 100644
index 0000000..0e22e44
--- /dev/null
+++ b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "BTAudioProviderLeAudioHW"
+
+#include "LeAudioOffloadAudioProvider.h"
+
+#include <BluetoothAudioCodecs.h>
+#include <BluetoothAudioSessionReport.h>
+#include <android-base/logging.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+LeAudioOffloadOutputAudioProvider::LeAudioOffloadOutputAudioProvider()
+    : LeAudioOffloadAudioProvider() {
+  session_type_ = SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
+}
+
+LeAudioOffloadInputAudioProvider::LeAudioOffloadInputAudioProvider()
+    : LeAudioOffloadAudioProvider() {
+  session_type_ = SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH;
+}
+
+LeAudioOffloadBroadcastAudioProvider::LeAudioOffloadBroadcastAudioProvider()
+    : LeAudioOffloadAudioProvider() {
+  session_type_ =
+      SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
+}
+
+LeAudioOffloadAudioProvider::LeAudioOffloadAudioProvider()
+    : BluetoothAudioProvider() {}
+
+bool LeAudioOffloadAudioProvider::isValid(const SessionType& sessionType) {
+  return (sessionType == session_type_);
+}
+
+ndk::ScopedAStatus LeAudioOffloadAudioProvider::startSession(
+    const std::shared_ptr<IBluetoothAudioPort>& host_if,
+    const AudioConfiguration& audio_config,
+    const std::vector<LatencyMode>& latency_modes, DataMQDesc* _aidl_return) {
+  if (audio_config.getTag() != AudioConfiguration::leAudioConfig) {
+    LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
+                 << audio_config.toString();
+    *_aidl_return = DataMQDesc();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+  const auto& le_audio_config =
+      audio_config.get<AudioConfiguration::leAudioConfig>();
+  if (!BluetoothAudioCodecs::IsOffloadLeAudioConfigurationValid(
+          session_type_, le_audio_config)) {
+    LOG(WARNING) << __func__ << " - Unsupported LC3 Offloaded Configuration="
+                 << le_audio_config.toString();
+    *_aidl_return = DataMQDesc();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+
+  return BluetoothAudioProvider::startSession(
+      host_if, audio_config, latency_modes, _aidl_return);
+}
+
+ndk::ScopedAStatus LeAudioOffloadAudioProvider::onSessionReady(
+    DataMQDesc* _aidl_return) {
+  BluetoothAudioSessionReport::OnSessionStarted(
+      session_type_, stack_iface_, nullptr, *audio_config_, latency_modes_);
+  *_aidl_return = DataMQDesc();
+  return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h
new file mode 100644
index 0000000..614c794
--- /dev/null
+++ b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h
@@ -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.
+ */
+
+#pragma once
+
+#include "BluetoothAudioProvider.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+class LeAudioOffloadAudioProvider : public BluetoothAudioProvider {
+ public:
+  LeAudioOffloadAudioProvider();
+
+  bool isValid(const SessionType& sessionType) override;
+
+  ndk::ScopedAStatus startSession(
+      const std::shared_ptr<IBluetoothAudioPort>& host_if,
+      const AudioConfiguration& audio_config,
+      const std::vector<LatencyMode>& latency_modes,
+      DataMQDesc* _aidl_return);
+
+ private:
+  ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) override;
+};
+
+class LeAudioOffloadOutputAudioProvider : public LeAudioOffloadAudioProvider {
+ public:
+  LeAudioOffloadOutputAudioProvider();
+};
+
+class LeAudioOffloadInputAudioProvider : public LeAudioOffloadAudioProvider {
+ public:
+  LeAudioOffloadInputAudioProvider();
+};
+
+class LeAudioOffloadBroadcastAudioProvider
+    : public LeAudioOffloadAudioProvider {
+ public:
+  LeAudioOffloadBroadcastAudioProvider();
+};
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.cpp b/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.cpp
new file mode 100644
index 0000000..c16ff54
--- /dev/null
+++ b/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.cpp
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "BTAudioProviderLeAudioSW"
+
+#include "LeAudioSoftwareAudioProvider.h"
+
+#include <BluetoothAudioCodecs.h>
+#include <BluetoothAudioSessionReport.h>
+#include <android-base/logging.h>
+
+#include <cstdint>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+static constexpr uint32_t kBufferOutCount = 2;  // two frame buffer
+static constexpr uint32_t kBufferInCount = 2;   // two frame buffer
+
+inline uint32_t channel_mode_to_channel_count(ChannelMode channel_mode) {
+  switch (channel_mode) {
+    case ChannelMode::MONO:
+      return 1;
+    case ChannelMode::STEREO:
+      return 2;
+    default:
+      return 0;
+  }
+  return 0;
+}
+
+LeAudioSoftwareOutputAudioProvider::LeAudioSoftwareOutputAudioProvider()
+    : LeAudioSoftwareAudioProvider() {
+  session_type_ = SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH;
+}
+
+LeAudioSoftwareInputAudioProvider::LeAudioSoftwareInputAudioProvider()
+    : LeAudioSoftwareAudioProvider() {
+  session_type_ = SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH;
+}
+
+LeAudioSoftwareBroadcastAudioProvider::LeAudioSoftwareBroadcastAudioProvider()
+    : LeAudioSoftwareAudioProvider() {
+  session_type_ = SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH;
+}
+
+LeAudioSoftwareAudioProvider::LeAudioSoftwareAudioProvider()
+    : BluetoothAudioProvider(), data_mq_(nullptr) {}
+
+bool LeAudioSoftwareAudioProvider::isValid(const SessionType& sessionType) {
+  return (sessionType == session_type_);
+}
+
+ndk::ScopedAStatus LeAudioSoftwareAudioProvider::startSession(
+    const std::shared_ptr<IBluetoothAudioPort>& host_if,
+    const AudioConfiguration& audio_config,
+    const std::vector<LatencyMode>& latency_modes, DataMQDesc* _aidl_return) {
+  if (audio_config.getTag() != AudioConfiguration::pcmConfig) {
+    LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
+                 << audio_config.toString();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+  const auto& pcm_config = audio_config.get<AudioConfiguration::pcmConfig>();
+  if (!BluetoothAudioCodecs::IsSoftwarePcmConfigurationValid(pcm_config)) {
+    LOG(WARNING) << __func__ << " - Unsupported PCM Configuration="
+                 << pcm_config.toString();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+
+  uint32_t buffer_modifier = 0;
+  if (session_type_ == SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH ||
+      session_type_ ==
+          SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH)
+    buffer_modifier = kBufferOutCount;
+  else if (session_type_ == SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH)
+    buffer_modifier = kBufferInCount;
+
+  // 24 bit audio stream is sent as unpacked
+  int bytes_per_sample =
+      (pcm_config.bitsPerSample == 24) ? 4 : (pcm_config.bitsPerSample / 8);
+
+  uint32_t data_mq_size =
+      (ceil(pcm_config.sampleRateHz) / 1000) *
+      channel_mode_to_channel_count(pcm_config.channelMode) * bytes_per_sample *
+      (pcm_config.dataIntervalUs / 1000) * buffer_modifier;
+  if (data_mq_size <= 0) {
+    LOG(ERROR) << __func__ << "Unexpected audio buffer size: " << data_mq_size
+               << ", SampleRateHz: " << pcm_config.sampleRateHz
+               << ", ChannelMode: " << toString(pcm_config.channelMode)
+               << ", BitsPerSample: "
+               << static_cast<int>(pcm_config.bitsPerSample)
+               << ", BytesPerSample: " << bytes_per_sample
+               << ", DataIntervalUs: " << pcm_config.dataIntervalUs
+               << ", SessionType: " << toString(session_type_);
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+
+  LOG(INFO) << __func__ << " - size of audio buffer " << data_mq_size
+            << " byte(s)";
+
+  std::unique_ptr<DataMQ> temp_data_mq(
+      new DataMQ(data_mq_size, /* EventFlag */ true));
+  if (temp_data_mq == nullptr || !temp_data_mq->isValid()) {
+    ALOGE_IF(!temp_data_mq, "failed to allocate data MQ");
+    ALOGE_IF(temp_data_mq && !temp_data_mq->isValid(), "data MQ is invalid");
+    *_aidl_return = DataMQDesc();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+  data_mq_ = std::move(temp_data_mq);
+
+  return BluetoothAudioProvider::startSession(
+      host_if, audio_config, latency_modes, _aidl_return);
+}
+
+ndk::ScopedAStatus LeAudioSoftwareAudioProvider::onSessionReady(
+    DataMQDesc* _aidl_return) {
+  if (data_mq_ == nullptr || !data_mq_->isValid()) {
+    *_aidl_return = DataMQDesc();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+  *_aidl_return = data_mq_->dupeDesc();
+  auto desc = data_mq_->dupeDesc();
+  BluetoothAudioSessionReport::OnSessionStarted(
+      session_type_, stack_iface_, &desc, *audio_config_, latency_modes_);
+  return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.h b/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.h
new file mode 100644
index 0000000..21243ff
--- /dev/null
+++ b/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.h
@@ -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.
+ */
+
+#pragma once
+
+#include "BluetoothAudioProvider.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+class LeAudioSoftwareAudioProvider : public BluetoothAudioProvider {
+ public:
+  LeAudioSoftwareAudioProvider();
+
+  bool isValid(const SessionType& sessionType) override;
+
+  ndk::ScopedAStatus startSession(
+      const std::shared_ptr<IBluetoothAudioPort>& host_if,
+      const AudioConfiguration& audio_config,
+      const std::vector<LatencyMode>& latency_modes,
+      DataMQDesc* _aidl_return);
+
+ private:
+  // audio data queue for software encoding
+  std::unique_ptr<DataMQ> data_mq_;
+
+  ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) override;
+};
+
+class LeAudioSoftwareOutputAudioProvider : public LeAudioSoftwareAudioProvider {
+ public:
+  LeAudioSoftwareOutputAudioProvider();
+};
+
+class LeAudioSoftwareInputAudioProvider : public LeAudioSoftwareAudioProvider {
+ public:
+  LeAudioSoftwareInputAudioProvider();
+};
+
+class LeAudioSoftwareBroadcastAudioProvider
+    : public LeAudioSoftwareAudioProvider {
+ public:
+  LeAudioSoftwareBroadcastAudioProvider();
+};
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
\ No newline at end of file
diff --git a/bluetooth/audio/aidl/default/bluetooth_audio.xml b/bluetooth/audio/aidl/default/bluetooth_audio.xml
new file mode 100644
index 0000000..1859a1a
--- /dev/null
+++ b/bluetooth/audio/aidl/default/bluetooth_audio.xml
@@ -0,0 +1,6 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.bluetooth.audio</name>
+        <fqname>IBluetoothAudioProviderFactory/default</fqname>
+    </hal>
+</manifest>
\ No newline at end of file
diff --git a/bluetooth/audio/aidl/default/service.cpp b/bluetooth/audio/aidl/default/service.cpp
new file mode 100644
index 0000000..f8f9cde
--- /dev/null
+++ b/bluetooth/audio/aidl/default/service.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.
+ */
+
+#define LOG_TAG "BtAudioAIDLService"
+
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <utils/Log.h>
+
+#include "BluetoothAudioProviderFactory.h"
+
+using ::aidl::android::hardware::bluetooth::audio::
+    BluetoothAudioProviderFactory;
+
+extern "C" __attribute__((visibility("default"))) binder_status_t
+createIBluetoothAudioProviderFactory() {
+  auto factory = ::ndk::SharedRefBase::make<BluetoothAudioProviderFactory>();
+  const std::string instance_name =
+      std::string() + BluetoothAudioProviderFactory::descriptor + "/default";
+  binder_status_t aidl_status = AServiceManager_addService(
+      factory->asBinder().get(), instance_name.c_str());
+  ALOGW_IF(aidl_status != STATUS_OK, "Could not register %s, status=%d",
+           instance_name.c_str(), aidl_status);
+  return aidl_status;
+}
\ No newline at end of file
diff --git a/bluetooth/audio/aidl/vts/Android.bp b/bluetooth/audio/aidl/vts/Android.bp
new file mode 100644
index 0000000..feb952e
--- /dev/null
+++ b/bluetooth/audio/aidl/vts/Android.bp
@@ -0,0 +1,32 @@
+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: "VtsHalBluetoothAudioTargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    tidy_timeout_srcs: ["VtsHalBluetoothAudioTargetTest.cpp"],
+    srcs: ["VtsHalBluetoothAudioTargetTest.cpp"],
+    shared_libs: [
+        "android.hardware.audio.common-V1-ndk",
+        "android.hardware.bluetooth.audio-V1-ndk",
+        "android.hardware.common-V2-ndk",
+        "android.hardware.common.fmq-V1-ndk",
+        "libbase",
+        "libbinder_ndk",
+        "libcutils",
+        "libfmq",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
diff --git a/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp b/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp
new file mode 100644
index 0000000..b599365
--- /dev/null
+++ b/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp
@@ -0,0 +1,2017 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/bluetooth/audio/BnBluetoothAudioPort.h>
+#include <aidl/android/hardware/bluetooth/audio/IBluetoothAudioPort.h>
+#include <aidl/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.h>
+#include <android/binder_auto_utils.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <fmq/AidlMessageQueue.h>
+
+#include <cstdint>
+#include <future>
+#include <unordered_set>
+#include <vector>
+
+using aidl::android::hardware::audio::common::SinkMetadata;
+using aidl::android::hardware::audio::common::SourceMetadata;
+using aidl::android::hardware::bluetooth::audio::AacCapabilities;
+using aidl::android::hardware::bluetooth::audio::AacConfiguration;
+using aidl::android::hardware::bluetooth::audio::AptxCapabilities;
+using aidl::android::hardware::bluetooth::audio::AptxConfiguration;
+using aidl::android::hardware::bluetooth::audio::AudioCapabilities;
+using aidl::android::hardware::bluetooth::audio::AudioConfiguration;
+using aidl::android::hardware::bluetooth::audio::BnBluetoothAudioPort;
+using aidl::android::hardware::bluetooth::audio::BroadcastCapability;
+using aidl::android::hardware::bluetooth::audio::ChannelMode;
+using aidl::android::hardware::bluetooth::audio::CodecCapabilities;
+using aidl::android::hardware::bluetooth::audio::CodecConfiguration;
+using aidl::android::hardware::bluetooth::audio::CodecType;
+using aidl::android::hardware::bluetooth::audio::IBluetoothAudioPort;
+using aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider;
+using aidl::android::hardware::bluetooth::audio::IBluetoothAudioProviderFactory;
+using aidl::android::hardware::bluetooth::audio::LatencyMode;
+using aidl::android::hardware::bluetooth::audio::Lc3Capabilities;
+using aidl::android::hardware::bluetooth::audio::Lc3Configuration;
+using aidl::android::hardware::bluetooth::audio::LdacCapabilities;
+using aidl::android::hardware::bluetooth::audio::LdacConfiguration;
+using aidl::android::hardware::bluetooth::audio::LeAudioBroadcastConfiguration;
+using aidl::android::hardware::bluetooth::audio::
+    LeAudioCodecCapabilitiesSetting;
+using aidl::android::hardware::bluetooth::audio::LeAudioCodecConfiguration;
+using aidl::android::hardware::bluetooth::audio::LeAudioConfiguration;
+using aidl::android::hardware::bluetooth::audio::PcmConfiguration;
+using aidl::android::hardware::bluetooth::audio::PresentationPosition;
+using aidl::android::hardware::bluetooth::audio::SbcAllocMethod;
+using aidl::android::hardware::bluetooth::audio::SbcCapabilities;
+using aidl::android::hardware::bluetooth::audio::SbcChannelMode;
+using aidl::android::hardware::bluetooth::audio::SbcConfiguration;
+using aidl::android::hardware::bluetooth::audio::SessionType;
+using aidl::android::hardware::bluetooth::audio::UnicastCapability;
+using aidl::android::hardware::common::fmq::MQDescriptor;
+using aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using android::AidlMessageQueue;
+using android::ProcessState;
+using android::String16;
+using ndk::ScopedAStatus;
+using ndk::SpAIBinder;
+
+using MqDataType = int8_t;
+using MqDataMode = SynchronizedReadWrite;
+using DataMQ = AidlMessageQueue<MqDataType, MqDataMode>;
+using DataMQDesc = MQDescriptor<MqDataType, MqDataMode>;
+
+// Constants
+
+static constexpr int32_t a2dp_sample_rates[] = {0, 44100, 48000, 88200, 96000};
+static constexpr int8_t a2dp_bits_per_samples[] = {0, 16, 24, 32};
+static constexpr ChannelMode a2dp_channel_modes[] = {
+    ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
+static constexpr CodecType a2dp_codec_types[] = {
+    CodecType::UNKNOWN, CodecType::SBC,          CodecType::AAC,
+    CodecType::APTX,    CodecType::APTX_HD,      CodecType::LDAC,
+    CodecType::LC3,     CodecType::APTX_ADAPTIVE};
+static std::vector<LatencyMode> latency_modes = {LatencyMode::FREE};
+// Helpers
+
+template <typename T>
+struct identity {
+  typedef T type;
+};
+
+template <class T>
+bool contained_in_vector(const std::vector<T>& vector,
+                         const typename identity<T>::type& target) {
+  return std::find(vector.begin(), vector.end(), target) != vector.end();
+}
+
+void copy_codec_specific(CodecConfiguration::CodecSpecific& dst,
+                         const CodecConfiguration::CodecSpecific& src) {
+  switch (src.getTag()) {
+    case CodecConfiguration::CodecSpecific::sbcConfig:
+      dst.set<CodecConfiguration::CodecSpecific::sbcConfig>(
+          src.get<CodecConfiguration::CodecSpecific::sbcConfig>());
+      break;
+    case CodecConfiguration::CodecSpecific::aacConfig:
+      dst.set<CodecConfiguration::CodecSpecific::aacConfig>(
+          src.get<CodecConfiguration::CodecSpecific::aacConfig>());
+      break;
+    case CodecConfiguration::CodecSpecific::ldacConfig:
+      dst.set<CodecConfiguration::CodecSpecific::ldacConfig>(
+          src.get<CodecConfiguration::CodecSpecific::ldacConfig>());
+      break;
+    case CodecConfiguration::CodecSpecific::aptxConfig:
+      dst.set<CodecConfiguration::CodecSpecific::aptxConfig>(
+          src.get<CodecConfiguration::CodecSpecific::aptxConfig>());
+      break;
+    case CodecConfiguration::CodecSpecific::lc3Config:
+      dst.set<CodecConfiguration::CodecSpecific::lc3Config>(
+          src.get<CodecConfiguration::CodecSpecific::lc3Config>());
+      break;
+    case CodecConfiguration::CodecSpecific::aptxAdaptiveConfig:
+      dst.set<CodecConfiguration::CodecSpecific::aptxAdaptiveConfig>(
+          src.get<CodecConfiguration::CodecSpecific::aptxAdaptiveConfig>());
+      break;
+    default:
+      break;
+  }
+}
+
+class BluetoothAudioPort : public BnBluetoothAudioPort {
+ public:
+  BluetoothAudioPort() {}
+
+  ndk::ScopedAStatus startStream(bool) { return ScopedAStatus::ok(); }
+
+  ndk::ScopedAStatus suspendStream() { return ScopedAStatus::ok(); }
+
+  ndk::ScopedAStatus stopStream() { return ScopedAStatus::ok(); }
+
+  ndk::ScopedAStatus getPresentationPosition(PresentationPosition*) {
+    return ScopedAStatus::ok();
+  }
+
+  ndk::ScopedAStatus updateSourceMetadata(const SourceMetadata&) {
+    return ScopedAStatus::ok();
+  }
+
+  ndk::ScopedAStatus updateSinkMetadata(const SinkMetadata&) {
+    return ScopedAStatus::ok();
+  }
+
+  ndk::ScopedAStatus setLatencyMode(const LatencyMode) {
+    return ScopedAStatus::ok();
+  }
+
+  ndk::ScopedAStatus setCodecType(const CodecType) {
+    return ScopedAStatus::ok();
+  }
+
+ protected:
+  virtual ~BluetoothAudioPort() = default;
+};
+
+class BluetoothAudioProviderFactoryAidl
+    : public testing::TestWithParam<std::string> {
+ public:
+  virtual void SetUp() override {
+    provider_factory_ = IBluetoothAudioProviderFactory::fromBinder(
+        SpAIBinder(AServiceManager_getService(GetParam().c_str())));
+    audio_provider_ = nullptr;
+    ASSERT_NE(provider_factory_, nullptr);
+  }
+
+  virtual void TearDown() override { provider_factory_ = nullptr; }
+
+  void GetProviderCapabilitiesHelper(const SessionType& session_type) {
+    temp_provider_capabilities_.clear();
+    auto aidl_retval = provider_factory_->getProviderCapabilities(
+        session_type, &temp_provider_capabilities_);
+    // AIDL calls should not be failed and callback has to be executed
+    ASSERT_TRUE(aidl_retval.isOk());
+    switch (session_type) {
+      case SessionType::UNKNOWN: {
+        ASSERT_TRUE(temp_provider_capabilities_.empty());
+      } break;
+      case SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH:
+      case SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH:
+      case SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH:
+      case SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH:
+      case SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH: {
+        // All software paths are mandatory and must have exact 1
+        // "PcmParameters"
+        ASSERT_EQ(temp_provider_capabilities_.size(), 1);
+        ASSERT_EQ(temp_provider_capabilities_[0].getTag(),
+                  AudioCapabilities::pcmCapabilities);
+      } break;
+      case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
+      case SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH: {
+        std::unordered_set<CodecType> codec_types;
+        // empty capability means offload is unsupported
+        for (auto& audio_capability : temp_provider_capabilities_) {
+          ASSERT_EQ(audio_capability.getTag(),
+                    AudioCapabilities::a2dpCapabilities);
+          const auto& codec_capabilities =
+              audio_capability.get<AudioCapabilities::a2dpCapabilities>();
+          // Every codec can present once at most
+          ASSERT_EQ(codec_types.count(codec_capabilities.codecType), 0);
+          switch (codec_capabilities.codecType) {
+            case CodecType::SBC:
+              ASSERT_EQ(codec_capabilities.capabilities.getTag(),
+                        CodecCapabilities::Capabilities::sbcCapabilities);
+              break;
+            case CodecType::AAC:
+              ASSERT_EQ(codec_capabilities.capabilities.getTag(),
+                        CodecCapabilities::Capabilities::aacCapabilities);
+              break;
+            case CodecType::APTX:
+            case CodecType::APTX_HD:
+              ASSERT_EQ(codec_capabilities.capabilities.getTag(),
+                        CodecCapabilities::Capabilities::aptxCapabilities);
+              break;
+            case CodecType::LDAC:
+              ASSERT_EQ(codec_capabilities.capabilities.getTag(),
+                        CodecCapabilities::Capabilities::ldacCapabilities);
+              break;
+            case CodecType::LC3:
+              ASSERT_EQ(codec_capabilities.capabilities.getTag(),
+                        CodecCapabilities::Capabilities::lc3Capabilities);
+              break;
+            case CodecType::APTX_ADAPTIVE:
+            case CodecType::VENDOR:
+            case CodecType::UNKNOWN:
+              break;
+          }
+          codec_types.insert(codec_capabilities.codecType);
+        }
+      } break;
+      case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
+      case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
+      case SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH: {
+        ASSERT_FALSE(temp_provider_capabilities_.empty());
+        for (auto audio_capability : temp_provider_capabilities_) {
+          ASSERT_EQ(audio_capability.getTag(),
+                    AudioCapabilities::leAudioCapabilities);
+        }
+      } break;
+      case SessionType::A2DP_SOFTWARE_DECODING_DATAPATH: {
+        if (!temp_provider_capabilities_.empty()) {
+          ASSERT_EQ(temp_provider_capabilities_.size(), 1);
+          ASSERT_EQ(temp_provider_capabilities_[0].getTag(),
+                    AudioCapabilities::pcmCapabilities);
+        }
+      } break;
+      default: {
+        ASSERT_TRUE(temp_provider_capabilities_.empty());
+      }
+    }
+  }
+
+  /***
+   * This helps to open the specified provider and check the openProvider()
+   * has corruct return values. BUT, to keep it simple, it does not consider
+   * the capability, and please do so at the SetUp of each session's test.
+   ***/
+  void OpenProviderHelper(const SessionType& session_type) {
+    auto aidl_retval =
+        provider_factory_->openProvider(session_type, &audio_provider_);
+    if (aidl_retval.isOk()) {
+      ASSERT_NE(session_type, SessionType::UNKNOWN);
+      ASSERT_NE(audio_provider_, nullptr);
+      audio_port_ = ndk::SharedRefBase::make<BluetoothAudioPort>();
+    } else {
+      // optional session type
+      ASSERT_TRUE(
+          session_type == SessionType::UNKNOWN ||
+          session_type ==
+              SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+          session_type ==
+              SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
+          session_type ==
+              SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+          session_type ==
+              SessionType::
+                  LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+          session_type ==
+              SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
+          session_type == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH);
+      ASSERT_EQ(audio_provider_, nullptr);
+    }
+  }
+
+  void GetA2dpOffloadCapabilityHelper(const CodecType& codec_type) {
+    temp_codec_capabilities_ = nullptr;
+    for (auto& codec_capability : temp_provider_capabilities_) {
+      auto& a2dp_capabilities =
+          codec_capability.get<AudioCapabilities::a2dpCapabilities>();
+      if (a2dp_capabilities.codecType != codec_type) {
+        continue;
+      }
+      temp_codec_capabilities_ = &a2dp_capabilities;
+    }
+  }
+
+  std::vector<CodecConfiguration::CodecSpecific>
+  GetSbcCodecSpecificSupportedList(bool supported) {
+    std::vector<CodecConfiguration::CodecSpecific> sbc_codec_specifics;
+    if (!supported) {
+      SbcConfiguration sbc_config{.sampleRateHz = 0, .bitsPerSample = 0};
+      sbc_codec_specifics.push_back(
+          CodecConfiguration::CodecSpecific(sbc_config));
+      return sbc_codec_specifics;
+    }
+    GetA2dpOffloadCapabilityHelper(CodecType::SBC);
+    if (temp_codec_capabilities_ == nullptr ||
+        temp_codec_capabilities_->codecType != CodecType::SBC) {
+      return sbc_codec_specifics;
+    }
+    // parse the capability
+    auto& sbc_capability =
+        temp_codec_capabilities_->capabilities
+            .get<CodecCapabilities::Capabilities::sbcCapabilities>();
+    if (sbc_capability.minBitpool > sbc_capability.maxBitpool) {
+      return sbc_codec_specifics;
+    }
+
+    // combine those parameters into one list of
+    // CodecConfiguration::CodecSpecific
+    for (int32_t sample_rate : sbc_capability.sampleRateHz) {
+      for (int8_t block_length : sbc_capability.blockLength) {
+        for (int8_t num_subbands : sbc_capability.numSubbands) {
+          for (int8_t bits_per_sample : sbc_capability.bitsPerSample) {
+            for (auto channel_mode : sbc_capability.channelMode) {
+              for (auto alloc_method : sbc_capability.allocMethod) {
+                SbcConfiguration sbc_data = {
+                    .sampleRateHz = sample_rate,
+                    .channelMode = channel_mode,
+                    .blockLength = block_length,
+                    .numSubbands = num_subbands,
+                    .allocMethod = alloc_method,
+                    .bitsPerSample = bits_per_sample,
+                    .minBitpool = sbc_capability.minBitpool,
+                    .maxBitpool = sbc_capability.maxBitpool};
+                sbc_codec_specifics.push_back(
+                    CodecConfiguration::CodecSpecific(sbc_data));
+              }
+            }
+          }
+        }
+      }
+    }
+    return sbc_codec_specifics;
+  }
+
+  std::vector<CodecConfiguration::CodecSpecific>
+  GetAacCodecSpecificSupportedList(bool supported) {
+    std::vector<CodecConfiguration::CodecSpecific> aac_codec_specifics;
+    if (!supported) {
+      AacConfiguration aac_config{.sampleRateHz = 0, .bitsPerSample = 0};
+      aac_codec_specifics.push_back(
+          CodecConfiguration::CodecSpecific(aac_config));
+      return aac_codec_specifics;
+    }
+    GetA2dpOffloadCapabilityHelper(CodecType::AAC);
+    if (temp_codec_capabilities_ == nullptr ||
+        temp_codec_capabilities_->codecType != CodecType::AAC) {
+      return aac_codec_specifics;
+    }
+    // parse the capability
+    auto& aac_capability =
+        temp_codec_capabilities_->capabilities
+            .get<CodecCapabilities::Capabilities::aacCapabilities>();
+
+    std::vector<bool> variable_bit_rate_enableds = {false};
+    if (aac_capability.variableBitRateSupported) {
+      variable_bit_rate_enableds.push_back(true);
+    }
+
+    // combine those parameters into one list of
+    // CodecConfiguration::CodecSpecific
+    for (auto object_type : aac_capability.objectType) {
+      for (int32_t sample_rate : aac_capability.sampleRateHz) {
+        for (auto channel_mode : aac_capability.channelMode) {
+          for (int8_t bits_per_sample : aac_capability.bitsPerSample) {
+            for (auto variable_bit_rate_enabled : variable_bit_rate_enableds) {
+              AacConfiguration aac_data{
+                  .objectType = object_type,
+                  .sampleRateHz = sample_rate,
+                  .channelMode = channel_mode,
+                  .variableBitRateEnabled = variable_bit_rate_enabled,
+                  .bitsPerSample = bits_per_sample};
+              aac_codec_specifics.push_back(
+                  CodecConfiguration::CodecSpecific(aac_data));
+            }
+          }
+        }
+      }
+    }
+    return aac_codec_specifics;
+  }
+
+  std::vector<CodecConfiguration::CodecSpecific>
+  GetLdacCodecSpecificSupportedList(bool supported) {
+    std::vector<CodecConfiguration::CodecSpecific> ldac_codec_specifics;
+    if (!supported) {
+      LdacConfiguration ldac_config{.sampleRateHz = 0, .bitsPerSample = 0};
+      ldac_codec_specifics.push_back(
+          CodecConfiguration::CodecSpecific(ldac_config));
+      return ldac_codec_specifics;
+    }
+    GetA2dpOffloadCapabilityHelper(CodecType::LDAC);
+    if (temp_codec_capabilities_ == nullptr ||
+        temp_codec_capabilities_->codecType != CodecType::LDAC) {
+      return ldac_codec_specifics;
+    }
+    // parse the capability
+    auto& ldac_capability =
+        temp_codec_capabilities_->capabilities
+            .get<CodecCapabilities::Capabilities::ldacCapabilities>();
+
+    // combine those parameters into one list of
+    // CodecConfiguration::CodecSpecific
+    for (int32_t sample_rate : ldac_capability.sampleRateHz) {
+      for (int8_t bits_per_sample : ldac_capability.bitsPerSample) {
+        for (auto channel_mode : ldac_capability.channelMode) {
+          for (auto quality_index : ldac_capability.qualityIndex) {
+            LdacConfiguration ldac_data{.sampleRateHz = sample_rate,
+                                        .channelMode = channel_mode,
+                                        .qualityIndex = quality_index,
+                                        .bitsPerSample = bits_per_sample};
+            ldac_codec_specifics.push_back(
+                CodecConfiguration::CodecSpecific(ldac_data));
+          }
+        }
+      }
+    }
+    return ldac_codec_specifics;
+  }
+
+  std::vector<CodecConfiguration::CodecSpecific>
+  GetAptxCodecSpecificSupportedList(bool is_hd, bool supported) {
+    std::vector<CodecConfiguration::CodecSpecific> aptx_codec_specifics;
+    if (!supported) {
+      AptxConfiguration aptx_config{.sampleRateHz = 0, .bitsPerSample = 0};
+      aptx_codec_specifics.push_back(
+          CodecConfiguration::CodecSpecific(aptx_config));
+      return aptx_codec_specifics;
+    }
+    GetA2dpOffloadCapabilityHelper(
+        (is_hd ? CodecType::APTX_HD : CodecType::APTX));
+    if (temp_codec_capabilities_ == nullptr) {
+      return aptx_codec_specifics;
+    }
+    if ((is_hd && temp_codec_capabilities_->codecType != CodecType::APTX_HD) ||
+        (!is_hd && temp_codec_capabilities_->codecType != CodecType::APTX)) {
+      return aptx_codec_specifics;
+    }
+
+    // parse the capability
+    auto& aptx_capability =
+        temp_codec_capabilities_->capabilities
+            .get<CodecCapabilities::Capabilities::aptxCapabilities>();
+
+    // combine those parameters into one list of
+    // CodecConfiguration::CodecSpecific
+    for (int8_t bits_per_sample : aptx_capability.bitsPerSample) {
+      for (int32_t sample_rate : aptx_capability.sampleRateHz) {
+        for (auto channel_mode : aptx_capability.channelMode) {
+          AptxConfiguration aptx_data{.sampleRateHz = sample_rate,
+                                      .channelMode = channel_mode,
+                                      .bitsPerSample = bits_per_sample};
+          aptx_codec_specifics.push_back(
+              CodecConfiguration::CodecSpecific(aptx_data));
+        }
+      }
+    }
+    return aptx_codec_specifics;
+  }
+
+  std::vector<CodecConfiguration::CodecSpecific>
+  GetLc3CodecSpecificSupportedList(bool supported) {
+    std::vector<CodecConfiguration::CodecSpecific> lc3_codec_specifics;
+    if (!supported) {
+      Lc3Configuration lc3_config{.samplingFrequencyHz = 0,
+                                  .frameDurationUs = 0};
+      lc3_codec_specifics.push_back(
+          CodecConfiguration::CodecSpecific(lc3_config));
+      return lc3_codec_specifics;
+    }
+    GetA2dpOffloadCapabilityHelper(CodecType::LC3);
+    if (temp_codec_capabilities_ == nullptr ||
+        temp_codec_capabilities_->codecType != CodecType::LC3) {
+      return lc3_codec_specifics;
+    }
+    // parse the capability
+    auto& lc3_capability =
+        temp_codec_capabilities_->capabilities
+            .get<CodecCapabilities::Capabilities::lc3Capabilities>();
+
+    // combine those parameters into one list of
+    // CodecConfiguration::CodecSpecific
+    for (int32_t samplingFrequencyHz : lc3_capability.samplingFrequencyHz) {
+      for (int32_t frameDurationUs : lc3_capability.frameDurationUs) {
+        for (auto channel_mode : lc3_capability.channelMode) {
+          Lc3Configuration lc3_data{.samplingFrequencyHz = samplingFrequencyHz,
+                                    .channelMode = channel_mode,
+                                    .frameDurationUs = frameDurationUs};
+          lc3_codec_specifics.push_back(
+              CodecConfiguration::CodecSpecific(lc3_data));
+        }
+      }
+    }
+    return lc3_codec_specifics;
+  }
+
+  bool IsPcmConfigSupported(const PcmConfiguration& pcm_config) {
+    if (temp_provider_capabilities_.size() != 1 ||
+        temp_provider_capabilities_[0].getTag() !=
+            AudioCapabilities::pcmCapabilities) {
+      return false;
+    }
+    auto pcm_capability = temp_provider_capabilities_[0]
+                              .get<AudioCapabilities::pcmCapabilities>();
+    return (contained_in_vector(pcm_capability.channelMode,
+                                pcm_config.channelMode) &&
+            contained_in_vector(pcm_capability.sampleRateHz,
+                                pcm_config.sampleRateHz) &&
+            contained_in_vector(pcm_capability.bitsPerSample,
+                                pcm_config.bitsPerSample));
+  }
+
+  std::shared_ptr<IBluetoothAudioProviderFactory> provider_factory_;
+  std::shared_ptr<IBluetoothAudioProvider> audio_provider_;
+  std::shared_ptr<IBluetoothAudioPort> audio_port_;
+  std::vector<AudioCapabilities> temp_provider_capabilities_;
+
+  // temp storage saves the specified codec capability by
+  // GetOffloadCodecCapabilityHelper()
+  CodecCapabilities* temp_codec_capabilities_;
+
+  static constexpr SessionType kSessionTypes[] = {
+      SessionType::UNKNOWN,
+      SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH,
+      SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
+      SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH,
+      SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH,
+      SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH,
+      SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
+      SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH,
+      SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH,
+      SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
+      SessionType::A2DP_SOFTWARE_DECODING_DATAPATH,
+      SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH,
+  };
+};
+
+/**
+ * Test whether we can get the FactoryService from HIDL
+ */
+TEST_P(BluetoothAudioProviderFactoryAidl, GetProviderFactoryService) {}
+
+/**
+ * Test whether we can open a provider for each provider returned by
+ * getProviderCapabilities() with non-empty capabalities
+ */
+TEST_P(BluetoothAudioProviderFactoryAidl,
+       OpenProviderAndCheckCapabilitiesBySession) {
+  for (auto session_type : kSessionTypes) {
+    GetProviderCapabilitiesHelper(session_type);
+    OpenProviderHelper(session_type);
+    // We must be able to open a provider if its getProviderCapabilities()
+    // returns non-empty list.
+    EXPECT_TRUE(temp_provider_capabilities_.empty() ||
+                audio_provider_ != nullptr);
+  }
+}
+
+/**
+ * openProvider A2DP_SOFTWARE_ENCODING_DATAPATH
+ */
+class BluetoothAudioProviderA2dpEncodingSoftwareAidl
+    : public BluetoothAudioProviderFactoryAidl {
+ public:
+  virtual void SetUp() override {
+    BluetoothAudioProviderFactoryAidl::SetUp();
+    GetProviderCapabilitiesHelper(SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH);
+    OpenProviderHelper(SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH);
+    ASSERT_NE(audio_provider_, nullptr);
+  }
+
+  virtual void TearDown() override {
+    audio_port_ = nullptr;
+    audio_provider_ = nullptr;
+    BluetoothAudioProviderFactoryAidl::TearDown();
+  }
+};
+
+/**
+ * Test whether we can open a provider of type
+ */
+TEST_P(BluetoothAudioProviderA2dpEncodingSoftwareAidl,
+       OpenA2dpEncodingSoftwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH can be started and stopped with
+ * different PCM config
+ */
+TEST_P(BluetoothAudioProviderA2dpEncodingSoftwareAidl,
+       StartAndEndA2dpEncodingSoftwareSessionWithPossiblePcmConfig) {
+  for (auto sample_rate : a2dp_sample_rates) {
+    for (auto bits_per_sample : a2dp_bits_per_samples) {
+      for (auto channel_mode : a2dp_channel_modes) {
+        PcmConfiguration pcm_config{
+            .sampleRateHz = sample_rate,
+            .bitsPerSample = bits_per_sample,
+            .channelMode = channel_mode,
+        };
+        bool is_codec_config_valid = IsPcmConfigSupported(pcm_config);
+        DataMQDesc mq_desc;
+        auto aidl_retval = audio_provider_->startSession(
+            audio_port_, AudioConfiguration(pcm_config), latency_modes,
+            &mq_desc);
+        DataMQ data_mq(mq_desc);
+
+        EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
+        if (is_codec_config_valid) {
+          EXPECT_TRUE(data_mq.isValid());
+        }
+        EXPECT_TRUE(audio_provider_->endSession().isOk());
+      }
+    }
+  }
+}
+
+/**
+ * openProvider A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH
+ */
+class BluetoothAudioProviderA2dpEncodingHardwareAidl
+    : public BluetoothAudioProviderFactoryAidl {
+ public:
+  virtual void SetUp() override {
+    BluetoothAudioProviderFactoryAidl::SetUp();
+    GetProviderCapabilitiesHelper(
+        SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
+    OpenProviderHelper(SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
+    ASSERT_TRUE(temp_provider_capabilities_.empty() ||
+                audio_provider_ != nullptr);
+  }
+
+  virtual void TearDown() override {
+    audio_port_ = nullptr;
+    audio_provider_ = nullptr;
+    BluetoothAudioProviderFactoryAidl::TearDown();
+  }
+
+  bool IsOffloadSupported() { return (temp_provider_capabilities_.size() > 0); }
+};
+
+/**
+ * Test whether we can open a provider of type
+ */
+TEST_P(BluetoothAudioProviderA2dpEncodingHardwareAidl,
+       OpenA2dpEncodingHardwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
+ * SBC hardware encoding config
+ */
+TEST_P(BluetoothAudioProviderA2dpEncodingHardwareAidl,
+       StartAndEndA2dpSbcEncodingHardwareSession) {
+  if (!IsOffloadSupported()) {
+    return;
+  }
+
+  CodecConfiguration codec_config = {
+      .codecType = CodecType::SBC,
+      .encodedAudioBitrate = 328000,
+      .peerMtu = 1005,
+      .isScmstEnabled = false,
+  };
+  auto sbc_codec_specifics = GetSbcCodecSpecificSupportedList(true);
+
+  for (auto& codec_specific : sbc_codec_specifics) {
+    copy_codec_specific(codec_config.config, codec_specific);
+    DataMQDesc mq_desc;
+    auto aidl_retval = audio_provider_->startSession(
+        audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);
+
+    ASSERT_TRUE(aidl_retval.isOk());
+    EXPECT_TRUE(audio_provider_->endSession().isOk());
+  }
+}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
+ * AAC hardware encoding config
+ */
+TEST_P(BluetoothAudioProviderA2dpEncodingHardwareAidl,
+       StartAndEndA2dpAacEncodingHardwareSession) {
+  if (!IsOffloadSupported()) {
+    return;
+  }
+
+  CodecConfiguration codec_config = {
+      .codecType = CodecType::AAC,
+      .encodedAudioBitrate = 320000,
+      .peerMtu = 1005,
+      .isScmstEnabled = false,
+  };
+  auto aac_codec_specifics = GetAacCodecSpecificSupportedList(true);
+
+  for (auto& codec_specific : aac_codec_specifics) {
+    copy_codec_specific(codec_config.config, codec_specific);
+    DataMQDesc mq_desc;
+    auto aidl_retval = audio_provider_->startSession(
+        audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);
+
+    ASSERT_TRUE(aidl_retval.isOk());
+    EXPECT_TRUE(audio_provider_->endSession().isOk());
+  }
+}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
+ * LDAC hardware encoding config
+ */
+TEST_P(BluetoothAudioProviderA2dpEncodingHardwareAidl,
+       StartAndEndA2dpLdacEncodingHardwareSession) {
+  if (!IsOffloadSupported()) {
+    return;
+  }
+
+  CodecConfiguration codec_config = {
+      .codecType = CodecType::LDAC,
+      .encodedAudioBitrate = 990000,
+      .peerMtu = 1005,
+      .isScmstEnabled = false,
+  };
+  auto ldac_codec_specifics = GetLdacCodecSpecificSupportedList(true);
+
+  for (auto& codec_specific : ldac_codec_specifics) {
+    copy_codec_specific(codec_config.config, codec_specific);
+    DataMQDesc mq_desc;
+    auto aidl_retval = audio_provider_->startSession(
+        audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);
+
+    ASSERT_TRUE(aidl_retval.isOk());
+    EXPECT_TRUE(audio_provider_->endSession().isOk());
+  }
+}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
+ * LDAC hardware encoding config
+ */
+TEST_P(BluetoothAudioProviderA2dpEncodingHardwareAidl,
+       StartAndEndA2dpLc3EncodingHardwareSession) {
+  if (!IsOffloadSupported()) {
+    return;
+  }
+
+  CodecConfiguration codec_config = {
+      .codecType = CodecType::LC3,
+      .encodedAudioBitrate = 990000,
+      .peerMtu = 1005,
+      .isScmstEnabled = false,
+  };
+  auto lc3_codec_specifics = GetLc3CodecSpecificSupportedList(true);
+
+  for (auto& codec_specific : lc3_codec_specifics) {
+    copy_codec_specific(codec_config.config, codec_specific);
+    DataMQDesc mq_desc;
+    auto aidl_retval = audio_provider_->startSession(
+        audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);
+
+    ASSERT_TRUE(aidl_retval.isOk());
+    EXPECT_TRUE(audio_provider_->endSession().isOk());
+  }
+}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
+ * AptX hardware encoding config
+ */
+TEST_P(BluetoothAudioProviderA2dpEncodingHardwareAidl,
+       StartAndEndA2dpAptxEncodingHardwareSession) {
+  if (!IsOffloadSupported()) {
+    return;
+  }
+
+  for (auto codec_type : {CodecType::APTX, CodecType::APTX_HD}) {
+    CodecConfiguration codec_config = {
+        .codecType = codec_type,
+        .encodedAudioBitrate =
+            (codec_type == CodecType::APTX ? 352000 : 576000),
+        .peerMtu = 1005,
+        .isScmstEnabled = false,
+    };
+
+    auto aptx_codec_specifics = GetAptxCodecSpecificSupportedList(
+        (codec_type == CodecType::APTX_HD ? true : false), true);
+
+    for (auto& codec_specific : aptx_codec_specifics) {
+      copy_codec_specific(codec_config.config, codec_specific);
+      DataMQDesc mq_desc;
+      auto aidl_retval = audio_provider_->startSession(
+          audio_port_, AudioConfiguration(codec_config), latency_modes,
+          &mq_desc);
+
+      ASSERT_TRUE(aidl_retval.isOk());
+      EXPECT_TRUE(audio_provider_->endSession().isOk());
+    }
+  }
+}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
+ * an invalid codec config
+ */
+TEST_P(BluetoothAudioProviderA2dpEncodingHardwareAidl,
+       StartAndEndA2dpEncodingHardwareSessionInvalidCodecConfig) {
+  if (!IsOffloadSupported()) {
+    return;
+  }
+  ASSERT_NE(audio_provider_, nullptr);
+
+  std::vector<CodecConfiguration::CodecSpecific> codec_specifics;
+  for (auto codec_type : a2dp_codec_types) {
+    switch (codec_type) {
+      case CodecType::SBC:
+        codec_specifics = GetSbcCodecSpecificSupportedList(false);
+        break;
+      case CodecType::AAC:
+        codec_specifics = GetAacCodecSpecificSupportedList(false);
+        break;
+      case CodecType::LDAC:
+        codec_specifics = GetLdacCodecSpecificSupportedList(false);
+        break;
+      case CodecType::APTX:
+        codec_specifics = GetAptxCodecSpecificSupportedList(false, false);
+        break;
+      case CodecType::APTX_HD:
+        codec_specifics = GetAptxCodecSpecificSupportedList(true, false);
+        break;
+      case CodecType::LC3:
+        codec_specifics = GetLc3CodecSpecificSupportedList(false);
+        continue;
+      case CodecType::APTX_ADAPTIVE:
+      case CodecType::VENDOR:
+      case CodecType::UNKNOWN:
+        codec_specifics.clear();
+        break;
+    }
+    if (codec_specifics.empty()) {
+      continue;
+    }
+
+    CodecConfiguration codec_config = {
+        .codecType = codec_type,
+        .encodedAudioBitrate = 328000,
+        .peerMtu = 1005,
+        .isScmstEnabled = false,
+    };
+    for (auto codec_specific : codec_specifics) {
+      copy_codec_specific(codec_config.config, codec_specific);
+      DataMQDesc mq_desc;
+      auto aidl_retval = audio_provider_->startSession(
+          audio_port_, AudioConfiguration(codec_config), latency_modes,
+          &mq_desc);
+
+      // AIDL call should fail on invalid codec
+      ASSERT_FALSE(aidl_retval.isOk());
+      EXPECT_TRUE(audio_provider_->endSession().isOk());
+    }
+  }
+}
+
+/**
+ * openProvider HEARING_AID_SOFTWARE_ENCODING_DATAPATH
+ */
+class BluetoothAudioProviderHearingAidSoftwareAidl
+    : public BluetoothAudioProviderFactoryAidl {
+ public:
+  virtual void SetUp() override {
+    BluetoothAudioProviderFactoryAidl::SetUp();
+    GetProviderCapabilitiesHelper(
+        SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH);
+    OpenProviderHelper(SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH);
+    ASSERT_NE(audio_provider_, nullptr);
+  }
+
+  virtual void TearDown() override {
+    audio_port_ = nullptr;
+    audio_provider_ = nullptr;
+    BluetoothAudioProviderFactoryAidl::TearDown();
+  }
+
+  static constexpr int32_t hearing_aid_sample_rates_[] = {0, 16000, 24000};
+  static constexpr int8_t hearing_aid_bits_per_samples_[] = {0, 16, 24};
+  static constexpr ChannelMode hearing_aid_channel_modes_[] = {
+      ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
+};
+
+/**
+ * Test whether we can open a provider of type
+ */
+TEST_P(BluetoothAudioProviderHearingAidSoftwareAidl,
+       OpenHearingAidSoftwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH can be started and
+ * stopped with different PCM config
+ */
+TEST_P(BluetoothAudioProviderHearingAidSoftwareAidl,
+       StartAndEndHearingAidSessionWithPossiblePcmConfig) {
+  for (int32_t sample_rate : hearing_aid_sample_rates_) {
+    for (int8_t bits_per_sample : hearing_aid_bits_per_samples_) {
+      for (auto channel_mode : hearing_aid_channel_modes_) {
+        PcmConfiguration pcm_config{
+            .sampleRateHz = sample_rate,
+            .bitsPerSample = bits_per_sample,
+            .channelMode = channel_mode,
+        };
+        bool is_codec_config_valid = IsPcmConfigSupported(pcm_config);
+        DataMQDesc mq_desc;
+        auto aidl_retval = audio_provider_->startSession(
+            audio_port_, AudioConfiguration(pcm_config), latency_modes,
+            &mq_desc);
+        DataMQ data_mq(mq_desc);
+
+        EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
+        if (is_codec_config_valid) {
+          EXPECT_TRUE(data_mq.isValid());
+        }
+        EXPECT_TRUE(audio_provider_->endSession().isOk());
+      }
+    }
+  }
+}
+
+/**
+ * openProvider LE_AUDIO_SOFTWARE_ENCODING_DATAPATH
+ */
+class BluetoothAudioProviderLeAudioOutputSoftwareAidl
+    : public BluetoothAudioProviderFactoryAidl {
+ public:
+  virtual void SetUp() override {
+    BluetoothAudioProviderFactoryAidl::SetUp();
+    GetProviderCapabilitiesHelper(
+        SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH);
+    OpenProviderHelper(SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH);
+    ASSERT_NE(audio_provider_, nullptr);
+  }
+
+  virtual void TearDown() override {
+    audio_port_ = nullptr;
+    audio_provider_ = nullptr;
+    BluetoothAudioProviderFactoryAidl::TearDown();
+  }
+
+  static constexpr int32_t le_audio_output_sample_rates_[] = {
+      0, 8000, 16000, 24000, 32000, 44100, 48000,
+  };
+  static constexpr int8_t le_audio_output_bits_per_samples_[] = {0, 16, 24};
+  static constexpr ChannelMode le_audio_output_channel_modes_[] = {
+      ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
+  static constexpr int32_t le_audio_output_data_interval_us_[] = {
+      0 /* Invalid */, 10000 /* Valid 10ms */};
+};
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH can be started and
+ * stopped
+ */
+TEST_P(BluetoothAudioProviderLeAudioOutputSoftwareAidl,
+       OpenLeAudioOutputSoftwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH can be started and
+ * stopped with different PCM config
+ */
+TEST_P(BluetoothAudioProviderLeAudioOutputSoftwareAidl,
+       StartAndEndLeAudioOutputSessionWithPossiblePcmConfig) {
+  for (auto sample_rate : le_audio_output_sample_rates_) {
+    for (auto bits_per_sample : le_audio_output_bits_per_samples_) {
+      for (auto channel_mode : le_audio_output_channel_modes_) {
+        for (auto data_interval_us : le_audio_output_data_interval_us_) {
+          PcmConfiguration pcm_config{
+              .sampleRateHz = sample_rate,
+              .bitsPerSample = bits_per_sample,
+              .channelMode = channel_mode,
+              .dataIntervalUs = data_interval_us,
+          };
+          bool is_codec_config_valid =
+              IsPcmConfigSupported(pcm_config) && pcm_config.dataIntervalUs > 0;
+          DataMQDesc mq_desc;
+          auto aidl_retval = audio_provider_->startSession(
+              audio_port_, AudioConfiguration(pcm_config), latency_modes,
+              &mq_desc);
+          DataMQ data_mq(mq_desc);
+
+          EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
+          if (is_codec_config_valid) {
+            EXPECT_TRUE(data_mq.isValid());
+          }
+          EXPECT_TRUE(audio_provider_->endSession().isOk());
+        }
+      }
+    }
+  }
+}
+
+/**
+ * openProvider LE_AUDIO_SOFTWARE_DECODING_DATAPATH
+ */
+class BluetoothAudioProviderLeAudioInputSoftwareAidl
+    : public BluetoothAudioProviderFactoryAidl {
+ public:
+  virtual void SetUp() override {
+    BluetoothAudioProviderFactoryAidl::SetUp();
+    GetProviderCapabilitiesHelper(
+        SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH);
+    OpenProviderHelper(SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH);
+    ASSERT_NE(audio_provider_, nullptr);
+  }
+
+  virtual void TearDown() override {
+    audio_port_ = nullptr;
+    audio_provider_ = nullptr;
+    BluetoothAudioProviderFactoryAidl::TearDown();
+  }
+
+  static constexpr int32_t le_audio_input_sample_rates_[] = {
+      0, 8000, 16000, 24000, 32000, 44100, 48000};
+  static constexpr int8_t le_audio_input_bits_per_samples_[] = {0, 16, 24};
+  static constexpr ChannelMode le_audio_input_channel_modes_[] = {
+      ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
+  static constexpr int32_t le_audio_input_data_interval_us_[] = {
+      0 /* Invalid */, 10000 /* Valid 10ms */};
+};
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH can be started and
+ * stopped
+ */
+TEST_P(BluetoothAudioProviderLeAudioInputSoftwareAidl,
+       OpenLeAudioInputSoftwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH can be started and
+ * stopped with different PCM config
+ */
+TEST_P(BluetoothAudioProviderLeAudioInputSoftwareAidl,
+       StartAndEndLeAudioInputSessionWithPossiblePcmConfig) {
+  for (auto sample_rate : le_audio_input_sample_rates_) {
+    for (auto bits_per_sample : le_audio_input_bits_per_samples_) {
+      for (auto channel_mode : le_audio_input_channel_modes_) {
+        for (auto data_interval_us : le_audio_input_data_interval_us_) {
+          PcmConfiguration pcm_config{
+              .sampleRateHz = sample_rate,
+              .bitsPerSample = bits_per_sample,
+              .channelMode = channel_mode,
+              .dataIntervalUs = data_interval_us,
+          };
+          bool is_codec_config_valid =
+              IsPcmConfigSupported(pcm_config) && pcm_config.dataIntervalUs > 0;
+          DataMQDesc mq_desc;
+          auto aidl_retval = audio_provider_->startSession(
+              audio_port_, AudioConfiguration(pcm_config), latency_modes,
+              &mq_desc);
+          DataMQ data_mq(mq_desc);
+
+          EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
+          if (is_codec_config_valid) {
+            EXPECT_TRUE(data_mq.isValid());
+          }
+          EXPECT_TRUE(audio_provider_->endSession().isOk());
+        }
+      }
+    }
+  }
+}
+
+/**
+ * openProvider LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH
+ */
+class BluetoothAudioProviderLeAudioOutputHardwareAidl
+    : public BluetoothAudioProviderFactoryAidl {
+ public:
+  virtual void SetUp() override {
+    BluetoothAudioProviderFactoryAidl::SetUp();
+    GetProviderCapabilitiesHelper(
+        SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
+    OpenProviderHelper(
+        SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
+    ASSERT_TRUE(temp_provider_capabilities_.empty() ||
+                audio_provider_ != nullptr);
+  }
+
+  virtual void TearDown() override {
+    audio_port_ = nullptr;
+    audio_provider_ = nullptr;
+    BluetoothAudioProviderFactoryAidl::TearDown();
+  }
+
+  bool IsOffloadOutputSupported() {
+    for (auto& capability : temp_provider_capabilities_) {
+      if (capability.getTag() != AudioCapabilities::leAudioCapabilities) {
+        continue;
+      }
+      auto& le_audio_capability =
+          capability.get<AudioCapabilities::leAudioCapabilities>();
+      if (le_audio_capability.unicastEncodeCapability.codecType !=
+          CodecType::UNKNOWN)
+        return true;
+    }
+    return false;
+  }
+
+  std::vector<Lc3Configuration> GetUnicastLc3SupportedList(bool decoding,
+                                                           bool supported) {
+    std::vector<Lc3Configuration> le_audio_codec_configs;
+    if (!supported) {
+      Lc3Configuration lc3_config{.samplingFrequencyHz = 0, .pcmBitDepth = 0};
+      le_audio_codec_configs.push_back(lc3_config);
+      return le_audio_codec_configs;
+    }
+
+    // There might be more than one LeAudioCodecCapabilitiesSetting
+    std::vector<Lc3Capabilities> lc3_capabilities;
+    for (auto& capability : temp_provider_capabilities_) {
+      if (capability.getTag() != AudioCapabilities::leAudioCapabilities) {
+        continue;
+      }
+      auto& le_audio_capability =
+          capability.get<AudioCapabilities::leAudioCapabilities>();
+      auto& unicast_capability =
+          decoding ? le_audio_capability.unicastDecodeCapability
+                   : le_audio_capability.unicastEncodeCapability;
+      if (unicast_capability.codecType != CodecType::LC3) {
+        continue;
+      }
+      auto& lc3_capability = unicast_capability.leAudioCodecCapabilities.get<
+          UnicastCapability::LeAudioCodecCapabilities::lc3Capabilities>();
+      lc3_capabilities.push_back(lc3_capability);
+    }
+
+    // Combine those parameters into one list of LeAudioCodecConfiguration
+    // This seems horrible, but usually each Lc3Capability only contains a
+    // single Lc3Configuration, which means every array has a length of 1.
+    for (auto& lc3_capability : lc3_capabilities) {
+      for (int32_t samplingFrequencyHz : lc3_capability.samplingFrequencyHz) {
+        for (int32_t frameDurationUs : lc3_capability.frameDurationUs) {
+          for (int32_t octetsPerFrame : lc3_capability.octetsPerFrame) {
+            Lc3Configuration lc3_config = {
+                .samplingFrequencyHz = samplingFrequencyHz,
+                .frameDurationUs = frameDurationUs,
+                .octetsPerFrame = octetsPerFrame,
+            };
+            le_audio_codec_configs.push_back(lc3_config);
+          }
+        }
+      }
+    }
+
+    return le_audio_codec_configs;
+  }
+
+  LeAudioCodecCapabilitiesSetting temp_le_audio_capabilities_;
+};
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
+ * stopped
+ */
+TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
+       OpenLeAudioOutputHardwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
+ * stopped with Unicast hardware encoding config
+ */
+TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
+       StartAndEndLeAudioOutputSessionWithPossibleUnicastConfig) {
+  if (!IsOffloadOutputSupported()) {
+    return;
+  }
+
+  auto lc3_codec_configs =
+      GetUnicastLc3SupportedList(false /* decoding */, true /* supported */);
+  LeAudioConfiguration le_audio_config = {
+      .codecType = CodecType::LC3,
+      .peerDelayUs = 0,
+  };
+
+  for (auto& lc3_config : lc3_codec_configs) {
+    le_audio_config.leAudioCodecConfig
+        .set<LeAudioCodecConfiguration::lc3Config>(lc3_config);
+    DataMQDesc mq_desc;
+    auto aidl_retval = audio_provider_->startSession(
+        audio_port_, AudioConfiguration(le_audio_config), latency_modes,
+        &mq_desc);
+
+    ASSERT_TRUE(aidl_retval.isOk());
+    EXPECT_TRUE(audio_provider_->endSession().isOk());
+  }
+}
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
+ * stopped with Unicast hardware encoding config
+ *
+ * Disabled since offload codec checking is not ready
+ */
+TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
+       DISABLED_StartAndEndLeAudioOutputSessionWithInvalidAudioConfiguration) {
+  if (!IsOffloadOutputSupported()) {
+    return;
+  }
+
+  auto lc3_codec_configs =
+      GetUnicastLc3SupportedList(false /* decoding */, false /* supported */);
+  LeAudioConfiguration le_audio_config = {
+      .codecType = CodecType::LC3,
+      .peerDelayUs = 0,
+  };
+
+  for (auto& lc3_config : lc3_codec_configs) {
+    le_audio_config.leAudioCodecConfig
+        .set<LeAudioCodecConfiguration::lc3Config>(lc3_config);
+    DataMQDesc mq_desc;
+    auto aidl_retval = audio_provider_->startSession(
+        audio_port_, AudioConfiguration(le_audio_config), latency_modes,
+        &mq_desc);
+
+    // AIDL call should fail on invalid codec
+    ASSERT_FALSE(aidl_retval.isOk());
+    EXPECT_TRUE(audio_provider_->endSession().isOk());
+  }
+}
+
+/**
+ * openProvider LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH
+ */
+class BluetoothAudioProviderLeAudioInputHardwareAidl
+    : public BluetoothAudioProviderLeAudioOutputHardwareAidl {
+ public:
+  virtual void SetUp() override {
+    BluetoothAudioProviderFactoryAidl::SetUp();
+    GetProviderCapabilitiesHelper(
+        SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
+    OpenProviderHelper(
+        SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
+    ASSERT_TRUE(temp_provider_capabilities_.empty() ||
+                audio_provider_ != nullptr);
+  }
+
+  bool IsOffloadInputSupported() {
+    for (auto& capability : temp_provider_capabilities_) {
+      if (capability.getTag() != AudioCapabilities::leAudioCapabilities) {
+        continue;
+      }
+      auto& le_audio_capability =
+          capability.get<AudioCapabilities::leAudioCapabilities>();
+      if (le_audio_capability.unicastDecodeCapability.codecType !=
+          CodecType::UNKNOWN)
+        return true;
+    }
+    return false;
+  }
+
+  virtual void TearDown() override {
+    audio_port_ = nullptr;
+    audio_provider_ = nullptr;
+    BluetoothAudioProviderFactoryAidl::TearDown();
+  }
+};
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
+ * stopped
+ */
+TEST_P(BluetoothAudioProviderLeAudioInputHardwareAidl,
+       OpenLeAudioInputHardwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
+ * stopped with Unicast hardware encoding config
+ */
+TEST_P(BluetoothAudioProviderLeAudioInputHardwareAidl,
+       StartAndEndLeAudioInputSessionWithPossibleUnicastConfig) {
+  if (!IsOffloadInputSupported()) {
+    return;
+  }
+
+  auto lc3_codec_configs =
+      GetUnicastLc3SupportedList(true /* decoding */, true /* supported */);
+  LeAudioConfiguration le_audio_config = {
+      .codecType = CodecType::LC3,
+      .peerDelayUs = 0,
+  };
+
+  for (auto& lc3_config : lc3_codec_configs) {
+    le_audio_config.leAudioCodecConfig
+        .set<LeAudioCodecConfiguration::lc3Config>(lc3_config);
+    DataMQDesc mq_desc;
+    auto aidl_retval = audio_provider_->startSession(
+        audio_port_, AudioConfiguration(le_audio_config), latency_modes,
+        &mq_desc);
+
+    ASSERT_TRUE(aidl_retval.isOk());
+    EXPECT_TRUE(audio_provider_->endSession().isOk());
+  }
+}
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
+ * stopped with Unicast hardware encoding config
+ *
+ * Disabled since offload codec checking is not ready
+ */
+TEST_P(BluetoothAudioProviderLeAudioInputHardwareAidl,
+       DISABLED_StartAndEndLeAudioInputSessionWithInvalidAudioConfiguration) {
+  if (!IsOffloadInputSupported()) {
+    return;
+  }
+
+  auto lc3_codec_configs =
+      GetUnicastLc3SupportedList(true /* decoding */, false /* supported */);
+  LeAudioConfiguration le_audio_config = {
+      .codecType = CodecType::LC3,
+      .peerDelayUs = 0,
+  };
+
+  for (auto& lc3_config : lc3_codec_configs) {
+    le_audio_config.leAudioCodecConfig
+        .set<LeAudioCodecConfiguration::lc3Config>(lc3_config);
+
+    DataMQDesc mq_desc;
+    auto aidl_retval = audio_provider_->startSession(
+        audio_port_, AudioConfiguration(le_audio_config), latency_modes,
+        &mq_desc);
+
+    // AIDL call should fail on invalid codec
+    ASSERT_FALSE(aidl_retval.isOk());
+    EXPECT_TRUE(audio_provider_->endSession().isOk());
+  }
+}
+
+/**
+ * openProvider LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH
+ */
+class BluetoothAudioProviderLeAudioBroadcastSoftwareAidl
+    : public BluetoothAudioProviderFactoryAidl {
+ public:
+  virtual void SetUp() override {
+    BluetoothAudioProviderFactoryAidl::SetUp();
+    GetProviderCapabilitiesHelper(
+        SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH);
+    OpenProviderHelper(
+        SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH);
+    ASSERT_NE(audio_provider_, nullptr);
+  }
+
+  virtual void TearDown() override {
+    audio_port_ = nullptr;
+    audio_provider_ = nullptr;
+    BluetoothAudioProviderFactoryAidl::TearDown();
+  }
+
+  static constexpr int32_t le_audio_output_sample_rates_[] = {
+      0, 8000, 16000, 24000, 32000, 44100, 48000,
+  };
+  static constexpr int8_t le_audio_output_bits_per_samples_[] = {0, 16, 24};
+  static constexpr ChannelMode le_audio_output_channel_modes_[] = {
+      ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
+  static constexpr int32_t le_audio_output_data_interval_us_[] = {
+      0 /* Invalid */, 10000 /* Valid 10ms */};
+};
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH can be started and
+ * stopped
+ */
+TEST_P(BluetoothAudioProviderLeAudioBroadcastSoftwareAidl,
+       OpenLeAudioOutputSoftwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH can be started and
+ * stopped with different PCM config
+ */
+TEST_P(BluetoothAudioProviderLeAudioBroadcastSoftwareAidl,
+       StartAndEndLeAudioOutputSessionWithPossiblePcmConfig) {
+  for (auto sample_rate : le_audio_output_sample_rates_) {
+    for (auto bits_per_sample : le_audio_output_bits_per_samples_) {
+      for (auto channel_mode : le_audio_output_channel_modes_) {
+        for (auto data_interval_us : le_audio_output_data_interval_us_) {
+          PcmConfiguration pcm_config{
+              .sampleRateHz = sample_rate,
+              .bitsPerSample = bits_per_sample,
+              .channelMode = channel_mode,
+              .dataIntervalUs = data_interval_us,
+          };
+          bool is_codec_config_valid =
+              IsPcmConfigSupported(pcm_config) && pcm_config.dataIntervalUs > 0;
+          DataMQDesc mq_desc;
+          auto aidl_retval = audio_provider_->startSession(
+              audio_port_, AudioConfiguration(pcm_config), latency_modes,
+              &mq_desc);
+          DataMQ data_mq(mq_desc);
+
+          EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
+          if (is_codec_config_valid) {
+            EXPECT_TRUE(data_mq.isValid());
+          }
+          EXPECT_TRUE(audio_provider_->endSession().isOk());
+        }
+      }
+    }
+  }
+}
+
+/**
+ * openProvider LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH
+ */
+class BluetoothAudioProviderLeAudioBroadcastHardwareAidl
+    : public BluetoothAudioProviderFactoryAidl {
+ public:
+  virtual void SetUp() override {
+    BluetoothAudioProviderFactoryAidl::SetUp();
+    GetProviderCapabilitiesHelper(
+        SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
+    OpenProviderHelper(
+        SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
+    ASSERT_TRUE(temp_provider_capabilities_.empty() ||
+                audio_provider_ != nullptr);
+  }
+
+  virtual void TearDown() override {
+    audio_port_ = nullptr;
+    audio_provider_ = nullptr;
+    BluetoothAudioProviderFactoryAidl::TearDown();
+  }
+
+  bool IsBroadcastOffloadSupported() {
+    for (auto& capability : temp_provider_capabilities_) {
+      if (capability.getTag() != AudioCapabilities::leAudioCapabilities) {
+        continue;
+      }
+      auto& le_audio_capability =
+          capability.get<AudioCapabilities::leAudioCapabilities>();
+      if (le_audio_capability.broadcastCapability.codecType !=
+          CodecType::UNKNOWN)
+        return true;
+    }
+    return false;
+  }
+
+  std::vector<Lc3Configuration> GetBroadcastLc3SupportedList(bool supported) {
+    std::vector<Lc3Configuration> le_audio_codec_configs;
+    if (!supported) {
+      Lc3Configuration lc3_config{.samplingFrequencyHz = 0, .pcmBitDepth = 0};
+      le_audio_codec_configs.push_back(lc3_config);
+      return le_audio_codec_configs;
+    }
+
+    // There might be more than one LeAudioCodecCapabilitiesSetting
+    std::vector<Lc3Capabilities> lc3_capabilities;
+    for (auto& capability : temp_provider_capabilities_) {
+      if (capability.getTag() != AudioCapabilities::leAudioCapabilities) {
+        continue;
+      }
+      auto& le_audio_capability =
+          capability.get<AudioCapabilities::leAudioCapabilities>();
+      auto& broadcast_capability = le_audio_capability.broadcastCapability;
+      if (broadcast_capability.codecType != CodecType::LC3) {
+        continue;
+      }
+      auto& lc3_capability = broadcast_capability.leAudioCodecCapabilities.get<
+          BroadcastCapability::LeAudioCodecCapabilities::lc3Capabilities>();
+      for (int idx = 0; idx < lc3_capability->size(); idx++)
+        lc3_capabilities.push_back(*lc3_capability->at(idx));
+    }
+
+    // Combine those parameters into one list of LeAudioCodecConfiguration
+    // This seems horrible, but usually each Lc3Capability only contains a
+    // single Lc3Configuration, which means every array has a length of 1.
+    for (auto& lc3_capability : lc3_capabilities) {
+      for (int32_t samplingFrequencyHz : lc3_capability.samplingFrequencyHz) {
+        for (int32_t frameDurationUs : lc3_capability.frameDurationUs) {
+          for (int32_t octetsPerFrame : lc3_capability.octetsPerFrame) {
+            Lc3Configuration lc3_config = {
+                .samplingFrequencyHz = samplingFrequencyHz,
+                .frameDurationUs = frameDurationUs,
+                .octetsPerFrame = octetsPerFrame,
+            };
+            le_audio_codec_configs.push_back(lc3_config);
+          }
+        }
+      }
+    }
+
+    return le_audio_codec_configs;
+  }
+
+  LeAudioCodecCapabilitiesSetting temp_le_audio_capabilities_;
+};
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be
+ * started and stopped
+ */
+TEST_P(BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
+       OpenLeAudioOutputHardwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be
+ * started and stopped with broadcast hardware encoding config
+ */
+TEST_P(BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
+       StartAndEndLeAudioBroadcastSessionWithPossibleBroadcastConfig) {
+  if (!IsBroadcastOffloadSupported()) {
+    return;
+  }
+
+  auto lc3_codec_configs = GetBroadcastLc3SupportedList(true /* supported */);
+  LeAudioBroadcastConfiguration le_audio_broadcast_config = {
+      .codecType = CodecType::LC3,
+      .streamMap = {},
+  };
+
+  for (auto& lc3_config : lc3_codec_configs) {
+    le_audio_broadcast_config.streamMap[0]
+        .leAudioCodecConfig.set<LeAudioCodecConfiguration::lc3Config>(
+            lc3_config);
+    DataMQDesc mq_desc;
+    auto aidl_retval = audio_provider_->startSession(
+        audio_port_, AudioConfiguration(le_audio_broadcast_config),
+        latency_modes, &mq_desc);
+
+    ASSERT_TRUE(aidl_retval.isOk());
+    EXPECT_TRUE(audio_provider_->endSession().isOk());
+  }
+}
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be
+ * started and stopped with Broadcast hardware encoding config
+ *
+ * Disabled since offload codec checking is not ready
+ */
+TEST_P(
+    BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
+    DISABLED_StartAndEndLeAudioBroadcastSessionWithInvalidAudioConfiguration) {
+  if (!IsBroadcastOffloadSupported()) {
+    return;
+  }
+
+  auto lc3_codec_configs = GetBroadcastLc3SupportedList(false /* supported */);
+  LeAudioBroadcastConfiguration le_audio_broadcast_config = {
+      .codecType = CodecType::LC3,
+      .streamMap = {},
+  };
+
+  for (auto& lc3_config : lc3_codec_configs) {
+    le_audio_broadcast_config.streamMap[0]
+        .leAudioCodecConfig.set<LeAudioCodecConfiguration::lc3Config>(
+            lc3_config);
+    DataMQDesc mq_desc;
+    auto aidl_retval = audio_provider_->startSession(
+        audio_port_, AudioConfiguration(le_audio_broadcast_config),
+        latency_modes, &mq_desc);
+
+    // AIDL call should fail on invalid codec
+    ASSERT_FALSE(aidl_retval.isOk());
+    EXPECT_TRUE(audio_provider_->endSession().isOk());
+  }
+}
+
+/**
+ * openProvider A2DP_SOFTWARE_DECODING_DATAPATH
+ */
+class BluetoothAudioProviderA2dpDecodingSoftwareAidl
+    : public BluetoothAudioProviderFactoryAidl {
+ public:
+  virtual void SetUp() override {
+    BluetoothAudioProviderFactoryAidl::SetUp();
+    GetProviderCapabilitiesHelper(SessionType::A2DP_SOFTWARE_DECODING_DATAPATH);
+    OpenProviderHelper(SessionType::A2DP_SOFTWARE_DECODING_DATAPATH);
+    ASSERT_TRUE(temp_provider_capabilities_.empty() ||
+                audio_provider_ != nullptr);
+  }
+
+  virtual void TearDown() override {
+    audio_port_ = nullptr;
+    audio_provider_ = nullptr;
+    BluetoothAudioProviderFactoryAidl::TearDown();
+  }
+};
+
+/**
+ * Test whether we can open a provider of type
+ */
+TEST_P(BluetoothAudioProviderA2dpDecodingSoftwareAidl,
+       OpenA2dpDecodingSoftwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_SOFTWARE_DECODING_DATAPATH can be started and stopped with
+ * different PCM config
+ */
+TEST_P(BluetoothAudioProviderA2dpDecodingSoftwareAidl,
+       StartAndEndA2dpDecodingSoftwareSessionWithPossiblePcmConfig) {
+  for (auto sample_rate : a2dp_sample_rates) {
+    for (auto bits_per_sample : a2dp_bits_per_samples) {
+      for (auto channel_mode : a2dp_channel_modes) {
+        PcmConfiguration pcm_config{
+            .sampleRateHz = sample_rate,
+            .bitsPerSample = bits_per_sample,
+            .channelMode = channel_mode,
+        };
+        bool is_codec_config_valid = IsPcmConfigSupported(pcm_config);
+        DataMQDesc mq_desc;
+        auto aidl_retval = audio_provider_->startSession(
+            audio_port_, AudioConfiguration(pcm_config), latency_modes,
+            &mq_desc);
+        DataMQ data_mq(mq_desc);
+
+        EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
+        if (is_codec_config_valid) {
+          EXPECT_TRUE(data_mq.isValid());
+        }
+        EXPECT_TRUE(audio_provider_->endSession().isOk());
+      }
+    }
+  }
+}
+
+/**
+ * openProvider A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH
+ */
+class BluetoothAudioProviderA2dpDecodingHardwareAidl
+    : public BluetoothAudioProviderFactoryAidl {
+ public:
+  virtual void SetUp() override {
+    BluetoothAudioProviderFactoryAidl::SetUp();
+    GetProviderCapabilitiesHelper(
+        SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH);
+    OpenProviderHelper(SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH);
+    ASSERT_TRUE(temp_provider_capabilities_.empty() ||
+                audio_provider_ != nullptr);
+  }
+
+  virtual void TearDown() override {
+    audio_port_ = nullptr;
+    audio_provider_ = nullptr;
+    BluetoothAudioProviderFactoryAidl::TearDown();
+  }
+
+  bool IsOffloadSupported() { return (temp_provider_capabilities_.size() > 0); }
+};
+
+/**
+ * Test whether we can open a provider of type
+ */
+TEST_P(BluetoothAudioProviderA2dpDecodingHardwareAidl,
+       OpenA2dpDecodingHardwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_HARDWARE_DECODING_DATAPATH can be started and stopped with
+ * SBC hardware encoding config
+ */
+TEST_P(BluetoothAudioProviderA2dpDecodingHardwareAidl,
+       StartAndEndA2dpSbcDecodingHardwareSession) {
+  if (!IsOffloadSupported()) {
+    return;
+  }
+
+  CodecConfiguration codec_config = {
+      .codecType = CodecType::SBC,
+      .encodedAudioBitrate = 328000,
+      .peerMtu = 1005,
+      .isScmstEnabled = false,
+  };
+  auto sbc_codec_specifics = GetSbcCodecSpecificSupportedList(true);
+
+  for (auto& codec_specific : sbc_codec_specifics) {
+    copy_codec_specific(codec_config.config, codec_specific);
+    DataMQDesc mq_desc;
+    auto aidl_retval = audio_provider_->startSession(
+        audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);
+
+    ASSERT_TRUE(aidl_retval.isOk());
+    EXPECT_TRUE(audio_provider_->endSession().isOk());
+  }
+}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_HARDWARE_DECODING_DATAPATH can be started and stopped with
+ * AAC hardware encoding config
+ */
+TEST_P(BluetoothAudioProviderA2dpDecodingHardwareAidl,
+       StartAndEndA2dpAacDecodingHardwareSession) {
+  if (!IsOffloadSupported()) {
+    return;
+  }
+
+  CodecConfiguration codec_config = {
+      .codecType = CodecType::AAC,
+      .encodedAudioBitrate = 320000,
+      .peerMtu = 1005,
+      .isScmstEnabled = false,
+  };
+  auto aac_codec_specifics = GetAacCodecSpecificSupportedList(true);
+
+  for (auto& codec_specific : aac_codec_specifics) {
+    copy_codec_specific(codec_config.config, codec_specific);
+    DataMQDesc mq_desc;
+    auto aidl_retval = audio_provider_->startSession(
+        audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);
+
+    ASSERT_TRUE(aidl_retval.isOk());
+    EXPECT_TRUE(audio_provider_->endSession().isOk());
+  }
+}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_HARDWARE_DECODING_DATAPATH can be started and stopped with
+ * LDAC hardware encoding config
+ */
+TEST_P(BluetoothAudioProviderA2dpDecodingHardwareAidl,
+       StartAndEndA2dpLdacDecodingHardwareSession) {
+  if (!IsOffloadSupported()) {
+    return;
+  }
+
+  CodecConfiguration codec_config = {
+      .codecType = CodecType::LDAC,
+      .encodedAudioBitrate = 990000,
+      .peerMtu = 1005,
+      .isScmstEnabled = false,
+  };
+  auto ldac_codec_specifics = GetLdacCodecSpecificSupportedList(true);
+
+  for (auto& codec_specific : ldac_codec_specifics) {
+    copy_codec_specific(codec_config.config, codec_specific);
+    DataMQDesc mq_desc;
+    auto aidl_retval = audio_provider_->startSession(
+        audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);
+
+    ASSERT_TRUE(aidl_retval.isOk());
+    EXPECT_TRUE(audio_provider_->endSession().isOk());
+  }
+}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_HARDWARE_DECODING_DATAPATH can be started and stopped with
+ * LDAC hardware encoding config
+ */
+TEST_P(BluetoothAudioProviderA2dpDecodingHardwareAidl,
+       StartAndEndA2dpLc3DecodingHardwareSession) {
+  if (!IsOffloadSupported()) {
+    return;
+  }
+
+  CodecConfiguration codec_config = {
+      .codecType = CodecType::LC3,
+      .encodedAudioBitrate = 990000,
+      .peerMtu = 1005,
+      .isScmstEnabled = false,
+  };
+  auto lc3_codec_specifics = GetLc3CodecSpecificSupportedList(true);
+
+  for (auto& codec_specific : lc3_codec_specifics) {
+    copy_codec_specific(codec_config.config, codec_specific);
+    DataMQDesc mq_desc;
+    auto aidl_retval = audio_provider_->startSession(
+        audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);
+
+    ASSERT_TRUE(aidl_retval.isOk());
+    EXPECT_TRUE(audio_provider_->endSession().isOk());
+  }
+}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_HARDWARE_DECODING_DATAPATH can be started and stopped with
+ * AptX hardware encoding config
+ */
+TEST_P(BluetoothAudioProviderA2dpDecodingHardwareAidl,
+       StartAndEndA2dpAptxDecodingHardwareSession) {
+  if (!IsOffloadSupported()) {
+    return;
+  }
+
+  for (auto codec_type : {CodecType::APTX, CodecType::APTX_HD}) {
+    CodecConfiguration codec_config = {
+        .codecType = codec_type,
+        .encodedAudioBitrate =
+            (codec_type == CodecType::APTX ? 352000 : 576000),
+        .peerMtu = 1005,
+        .isScmstEnabled = false,
+    };
+
+    auto aptx_codec_specifics = GetAptxCodecSpecificSupportedList(
+        (codec_type == CodecType::APTX_HD ? true : false), true);
+
+    for (auto& codec_specific : aptx_codec_specifics) {
+      copy_codec_specific(codec_config.config, codec_specific);
+      DataMQDesc mq_desc;
+      auto aidl_retval = audio_provider_->startSession(
+          audio_port_, AudioConfiguration(codec_config), latency_modes,
+          &mq_desc);
+
+      ASSERT_TRUE(aidl_retval.isOk());
+      EXPECT_TRUE(audio_provider_->endSession().isOk());
+    }
+  }
+}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_HARDWARE_DECODING_DATAPATH can be started and stopped with
+ * an invalid codec config
+ */
+TEST_P(BluetoothAudioProviderA2dpDecodingHardwareAidl,
+       StartAndEndA2dpDecodingHardwareSessionInvalidCodecConfig) {
+  if (!IsOffloadSupported()) {
+    return;
+  }
+  ASSERT_NE(audio_provider_, nullptr);
+
+  std::vector<CodecConfiguration::CodecSpecific> codec_specifics;
+  for (auto codec_type : a2dp_codec_types) {
+    switch (codec_type) {
+      case CodecType::SBC:
+        codec_specifics = GetSbcCodecSpecificSupportedList(false);
+        break;
+      case CodecType::AAC:
+        codec_specifics = GetAacCodecSpecificSupportedList(false);
+        break;
+      case CodecType::LDAC:
+        codec_specifics = GetLdacCodecSpecificSupportedList(false);
+        break;
+      case CodecType::APTX:
+        codec_specifics = GetAptxCodecSpecificSupportedList(false, false);
+        break;
+      case CodecType::APTX_HD:
+        codec_specifics = GetAptxCodecSpecificSupportedList(true, false);
+        break;
+      case CodecType::LC3:
+        codec_specifics = GetLc3CodecSpecificSupportedList(false);
+        continue;
+      case CodecType::APTX_ADAPTIVE:
+      case CodecType::VENDOR:
+      case CodecType::UNKNOWN:
+        codec_specifics.clear();
+        break;
+    }
+    if (codec_specifics.empty()) {
+      continue;
+    }
+
+    CodecConfiguration codec_config = {
+        .codecType = codec_type,
+        .encodedAudioBitrate = 328000,
+        .peerMtu = 1005,
+        .isScmstEnabled = false,
+    };
+    for (auto codec_specific : codec_specifics) {
+      copy_codec_specific(codec_config.config, codec_specific);
+      DataMQDesc mq_desc;
+      auto aidl_retval = audio_provider_->startSession(
+          audio_port_, AudioConfiguration(codec_config), latency_modes,
+          &mq_desc);
+
+      // AIDL call should fail on invalid codec
+      ASSERT_FALSE(aidl_retval.isOk());
+      EXPECT_TRUE(audio_provider_->endSession().isOk());
+    }
+  }
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+    BluetoothAudioProviderFactoryAidl);
+INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProviderFactoryAidl,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(
+                             IBluetoothAudioProviderFactory::descriptor)),
+                         android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+    BluetoothAudioProviderA2dpEncodingSoftwareAidl);
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+                         BluetoothAudioProviderA2dpEncodingSoftwareAidl,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(
+                             IBluetoothAudioProviderFactory::descriptor)),
+                         android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+    BluetoothAudioProviderA2dpEncodingHardwareAidl);
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+                         BluetoothAudioProviderA2dpEncodingHardwareAidl,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(
+                             IBluetoothAudioProviderFactory::descriptor)),
+                         android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+    BluetoothAudioProviderHearingAidSoftwareAidl);
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+                         BluetoothAudioProviderHearingAidSoftwareAidl,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(
+                             IBluetoothAudioProviderFactory::descriptor)),
+                         android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+    BluetoothAudioProviderLeAudioOutputSoftwareAidl);
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+                         BluetoothAudioProviderLeAudioOutputSoftwareAidl,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(
+                             IBluetoothAudioProviderFactory::descriptor)),
+                         android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+    BluetoothAudioProviderLeAudioInputSoftwareAidl);
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+                         BluetoothAudioProviderLeAudioInputSoftwareAidl,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(
+                             IBluetoothAudioProviderFactory::descriptor)),
+                         android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+    BluetoothAudioProviderLeAudioOutputHardwareAidl);
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+                         BluetoothAudioProviderLeAudioOutputHardwareAidl,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(
+                             IBluetoothAudioProviderFactory::descriptor)),
+                         android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+    BluetoothAudioProviderLeAudioInputHardwareAidl);
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+                         BluetoothAudioProviderLeAudioInputHardwareAidl,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(
+                             IBluetoothAudioProviderFactory::descriptor)),
+                         android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+    BluetoothAudioProviderLeAudioBroadcastSoftwareAidl);
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+                         BluetoothAudioProviderLeAudioBroadcastSoftwareAidl,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(
+                             IBluetoothAudioProviderFactory::descriptor)),
+                         android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+    BluetoothAudioProviderLeAudioBroadcastHardwareAidl);
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+                         BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(
+                             IBluetoothAudioProviderFactory::descriptor)),
+                         android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+    BluetoothAudioProviderA2dpDecodingSoftwareAidl);
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+                         BluetoothAudioProviderA2dpDecodingSoftwareAidl,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(
+                             IBluetoothAudioProviderFactory::descriptor)),
+                         android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+    BluetoothAudioProviderA2dpDecodingHardwareAidl);
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+                         BluetoothAudioProviderA2dpDecodingHardwareAidl,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(
+                             IBluetoothAudioProviderFactory::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/bluetooth/audio/utils/Android.bp b/bluetooth/audio/utils/Android.bp
index 551bc50..42f9455 100644
--- a/bluetooth/audio/utils/Android.bp
+++ b/bluetooth/audio/utils/Android.bp
@@ -20,6 +20,7 @@
     export_include_dirs: ["session/"],
     header_libs: ["libhardware_headers"],
     shared_libs: [
+        "android.hardware.audio.common@5.0",
         "android.hardware.bluetooth.audio@2.0",
         "android.hardware.bluetooth.audio@2.1",
         "libbase",
@@ -28,5 +29,29 @@
         "libhidlbase",
         "liblog",
         "libutils",
+        "libbluetooth_audio_session_aidl",
+    ],
+}
+
+cc_library_shared {
+    name: "libbluetooth_audio_session_aidl",
+    vendor: true,
+    srcs: [
+        "aidl_session/BluetoothAudioCodecs.cpp",
+        "aidl_session/BluetoothAudioSession.cpp",
+        "aidl_session/HidlToAidlMiddleware.cpp",
+    ],
+    export_include_dirs: ["aidl_session/"],
+    header_libs: ["libhardware_headers"],
+    shared_libs: [
+        "android.hardware.bluetooth.audio@2.0",
+        "android.hardware.bluetooth.audio@2.1",
+        "libbase",
+        "libcutils",
+        "libbinder_ndk",
+        "libfmq",
+        "liblog",
+        "android.hardware.bluetooth.audio-V1-ndk",
+        "libhidlbase",
     ],
 }
diff --git a/bluetooth/audio/utils/OWNERS b/bluetooth/audio/utils/OWNERS
deleted file mode 100644
index a35dde2..0000000
--- a/bluetooth/audio/utils/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-include platform/system/bt:/OWNERS
-
-cheneyni@google.com
\ No newline at end of file
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp
new file mode 100644
index 0000000..1fb0e41
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp
@@ -0,0 +1,517 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "BTAudioCodecsAidl"
+
+#include "BluetoothAudioCodecs.h"
+
+#include <aidl/android/hardware/bluetooth/audio/AacCapabilities.h>
+#include <aidl/android/hardware/bluetooth/audio/AacObjectType.h>
+#include <aidl/android/hardware/bluetooth/audio/AptxCapabilities.h>
+#include <aidl/android/hardware/bluetooth/audio/ChannelMode.h>
+#include <aidl/android/hardware/bluetooth/audio/LdacCapabilities.h>
+#include <aidl/android/hardware/bluetooth/audio/LdacChannelMode.h>
+#include <aidl/android/hardware/bluetooth/audio/LdacQualityIndex.h>
+#include <aidl/android/hardware/bluetooth/audio/LeAudioConfiguration.h>
+#include <aidl/android/hardware/bluetooth/audio/SbcCapabilities.h>
+#include <aidl/android/hardware/bluetooth/audio/SbcChannelMode.h>
+#include <android-base/logging.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+static const PcmCapabilities kDefaultSoftwarePcmCapabilities = {
+    .sampleRateHz = {16000, 24000, 32000, 44100, 48000, 88200, 96000},
+    .channelMode = {ChannelMode::MONO, ChannelMode::STEREO},
+    .bitsPerSample = {16, 24, 32},
+    .dataIntervalUs = {},
+};
+
+static const SbcCapabilities kDefaultOffloadSbcCapability = {
+    .sampleRateHz = {44100},
+    .channelMode = {SbcChannelMode::MONO, SbcChannelMode::JOINT_STEREO},
+    .blockLength = {4, 8, 12, 16},
+    .numSubbands = {8},
+    .allocMethod = {SbcAllocMethod::ALLOC_MD_L},
+    .bitsPerSample = {16},
+    .minBitpool = 2,
+    .maxBitpool = 53};
+
+static const AacCapabilities kDefaultOffloadAacCapability = {
+    .objectType = {AacObjectType::MPEG2_LC},
+    .sampleRateHz = {44100},
+    .channelMode = {ChannelMode::STEREO},
+    .variableBitRateSupported = true,
+    .bitsPerSample = {16}};
+
+static const LdacCapabilities kDefaultOffloadLdacCapability = {
+    .sampleRateHz = {44100, 48000, 88200, 96000},
+    .channelMode = {LdacChannelMode::DUAL, LdacChannelMode::STEREO},
+    .qualityIndex = {LdacQualityIndex::HIGH},
+    .bitsPerSample = {16, 24, 32}};
+
+static const AptxCapabilities kDefaultOffloadAptxCapability = {
+    .sampleRateHz = {44100, 48000},
+    .channelMode = {ChannelMode::STEREO},
+    .bitsPerSample = {16},
+};
+
+static const AptxCapabilities kDefaultOffloadAptxHdCapability = {
+    .sampleRateHz = {44100, 48000},
+    .channelMode = {ChannelMode::STEREO},
+    .bitsPerSample = {24},
+};
+
+static const Lc3Capabilities kDefaultA2dpOffloadLc3Capability = {
+    .samplingFrequencyHz = {44100, 48000},
+    .frameDurationUs = {7500, 10000},
+    .channelMode = {ChannelMode::MONO, ChannelMode::STEREO},
+};
+
+const std::vector<CodecCapabilities> kDefaultOffloadA2dpCodecCapabilities = {
+    {.codecType = CodecType::SBC, .capabilities = {}},
+    {.codecType = CodecType::AAC, .capabilities = {}},
+    {.codecType = CodecType::LDAC, .capabilities = {}},
+    {.codecType = CodecType::APTX, .capabilities = {}},
+    {.codecType = CodecType::APTX_HD, .capabilities = {}},
+    {.codecType = CodecType::LC3, .capabilities = {}}};
+
+std::vector<LeAudioCodecCapabilitiesSetting> kDefaultOffloadLeAudioCapabilities;
+
+static const UnicastCapability kInvalidUnicastCapability = {
+    .codecType = CodecType::UNKNOWN};
+
+static const BroadcastCapability kInvalidBroadcastCapability = {
+    .codecType = CodecType::UNKNOWN};
+
+// Default Supported Codecs
+// LC3 16_1: sample rate: 16 kHz, frame duration: 7.5 ms, octets per frame: 30
+static const Lc3Capabilities kLc3Capability_16_1 = {
+    .samplingFrequencyHz = {16000},
+    .frameDurationUs = {7500},
+    .octetsPerFrame = {30}};
+
+// Default Supported Codecs
+// LC3 16_2: sample rate: 16 kHz, frame duration: 10 ms, octets per frame: 40
+static const Lc3Capabilities kLc3Capability_16_2 = {
+    .samplingFrequencyHz = {16000},
+    .frameDurationUs = {10000},
+    .octetsPerFrame = {40}};
+
+// Default Supported Codecs
+// LC3 24_2: sample rate: 24 kHz, frame duration: 10 ms, octets per frame: 60
+static const Lc3Capabilities kLc3Capability_24_2 = {
+    .samplingFrequencyHz = {24000},
+    .frameDurationUs = {10000},
+    .octetsPerFrame = {60}};
+
+// Default Supported Codecs
+// LC3 32_2: sample rate: 32 kHz, frame duration: 10 ms, octets per frame: 80
+static const Lc3Capabilities kLc3Capability_32_2 = {
+    .samplingFrequencyHz = {32000},
+    .frameDurationUs = {10000},
+    .octetsPerFrame = {80}};
+
+// Default Supported Codecs
+// LC3 48_4: sample rate: 48 kHz, frame duration: 10 ms, octets per frame: 120
+static const Lc3Capabilities kLc3Capability_48_4 = {
+    .samplingFrequencyHz = {48000},
+    .frameDurationUs = {10000},
+    .octetsPerFrame = {120}};
+
+static const std::vector<Lc3Capabilities> supportedLc3CapabilityList = {
+    kLc3Capability_48_4, kLc3Capability_32_2, kLc3Capability_24_2,
+    kLc3Capability_16_2, kLc3Capability_16_1};
+
+static AudioLocation stereoAudio = static_cast<AudioLocation>(
+    static_cast<uint8_t>(AudioLocation::FRONT_LEFT) |
+    static_cast<uint8_t>(AudioLocation::FRONT_RIGHT));
+static AudioLocation monoAudio = AudioLocation::UNKNOWN;
+
+// Stores the supported setting of audio location, connected device, and the
+// channel count for each device
+std::vector<std::tuple<AudioLocation, uint8_t, uint8_t>>
+    supportedDeviceSetting = {
+        // Stereo, two connected device, one for L one for R
+        std::make_tuple(stereoAudio, 2, 1),
+        // Stereo, one connected device for both L and R
+        std::make_tuple(stereoAudio, 1, 2),
+        // Mono
+        std::make_tuple(monoAudio, 1, 1)};
+
+template <class T>
+bool BluetoothAudioCodecs::ContainedInVector(
+    const std::vector<T>& vector, const typename identity<T>::type& target) {
+  return std::find(vector.begin(), vector.end(), target) != vector.end();
+}
+
+bool BluetoothAudioCodecs::IsOffloadSbcConfigurationValid(
+    const CodecConfiguration::CodecSpecific& codec_specific) {
+  if (codec_specific.getTag() != CodecConfiguration::CodecSpecific::sbcConfig) {
+    LOG(WARNING) << __func__
+                 << ": Invalid CodecSpecific=" << codec_specific.toString();
+    return false;
+  }
+  const SbcConfiguration sbc_data =
+      codec_specific.get<CodecConfiguration::CodecSpecific::sbcConfig>();
+
+  if (ContainedInVector(kDefaultOffloadSbcCapability.sampleRateHz,
+                        sbc_data.sampleRateHz) &&
+      ContainedInVector(kDefaultOffloadSbcCapability.blockLength,
+                        sbc_data.blockLength) &&
+      ContainedInVector(kDefaultOffloadSbcCapability.numSubbands,
+                        sbc_data.numSubbands) &&
+      ContainedInVector(kDefaultOffloadSbcCapability.bitsPerSample,
+                        sbc_data.bitsPerSample) &&
+      ContainedInVector(kDefaultOffloadSbcCapability.channelMode,
+                        sbc_data.channelMode) &&
+      ContainedInVector(kDefaultOffloadSbcCapability.allocMethod,
+                        sbc_data.allocMethod) &&
+      sbc_data.minBitpool <= sbc_data.maxBitpool &&
+      kDefaultOffloadSbcCapability.minBitpool <= sbc_data.minBitpool &&
+      kDefaultOffloadSbcCapability.maxBitpool >= sbc_data.maxBitpool) {
+    return true;
+  }
+  LOG(WARNING) << __func__
+               << ": Unsupported CodecSpecific=" << codec_specific.toString();
+  return false;
+}
+
+bool BluetoothAudioCodecs::IsOffloadAacConfigurationValid(
+    const CodecConfiguration::CodecSpecific& codec_specific) {
+  if (codec_specific.getTag() != CodecConfiguration::CodecSpecific::aacConfig) {
+    LOG(WARNING) << __func__
+                 << ": Invalid CodecSpecific=" << codec_specific.toString();
+    return false;
+  }
+  const AacConfiguration aac_data =
+      codec_specific.get<CodecConfiguration::CodecSpecific::aacConfig>();
+
+  if (ContainedInVector(kDefaultOffloadAacCapability.sampleRateHz,
+                        aac_data.sampleRateHz) &&
+      ContainedInVector(kDefaultOffloadAacCapability.bitsPerSample,
+                        aac_data.bitsPerSample) &&
+      ContainedInVector(kDefaultOffloadAacCapability.channelMode,
+                        aac_data.channelMode) &&
+      ContainedInVector(kDefaultOffloadAacCapability.objectType,
+                        aac_data.objectType) &&
+      (!aac_data.variableBitRateEnabled ||
+       kDefaultOffloadAacCapability.variableBitRateSupported)) {
+    return true;
+  }
+  LOG(WARNING) << __func__
+               << ": Unsupported CodecSpecific=" << codec_specific.toString();
+  return false;
+}
+
+bool BluetoothAudioCodecs::IsOffloadLdacConfigurationValid(
+    const CodecConfiguration::CodecSpecific& codec_specific) {
+  if (codec_specific.getTag() !=
+      CodecConfiguration::CodecSpecific::ldacConfig) {
+    LOG(WARNING) << __func__
+                 << ": Invalid CodecSpecific=" << codec_specific.toString();
+    return false;
+  }
+  const LdacConfiguration ldac_data =
+      codec_specific.get<CodecConfiguration::CodecSpecific::ldacConfig>();
+
+  if (ContainedInVector(kDefaultOffloadLdacCapability.sampleRateHz,
+                        ldac_data.sampleRateHz) &&
+      ContainedInVector(kDefaultOffloadLdacCapability.bitsPerSample,
+                        ldac_data.bitsPerSample) &&
+      ContainedInVector(kDefaultOffloadLdacCapability.channelMode,
+                        ldac_data.channelMode) &&
+      ContainedInVector(kDefaultOffloadLdacCapability.qualityIndex,
+                        ldac_data.qualityIndex)) {
+    return true;
+  }
+  LOG(WARNING) << __func__
+               << ": Unsupported CodecSpecific=" << codec_specific.toString();
+  return false;
+}
+
+bool BluetoothAudioCodecs::IsOffloadAptxConfigurationValid(
+    const CodecConfiguration::CodecSpecific& codec_specific) {
+  if (codec_specific.getTag() !=
+      CodecConfiguration::CodecSpecific::aptxConfig) {
+    LOG(WARNING) << __func__
+                 << ": Invalid CodecSpecific=" << codec_specific.toString();
+    return false;
+  }
+  const AptxConfiguration aptx_data =
+      codec_specific.get<CodecConfiguration::CodecSpecific::aptxConfig>();
+
+  if (ContainedInVector(kDefaultOffloadAptxCapability.sampleRateHz,
+                        aptx_data.sampleRateHz) &&
+      ContainedInVector(kDefaultOffloadAptxCapability.bitsPerSample,
+                        aptx_data.bitsPerSample) &&
+      ContainedInVector(kDefaultOffloadAptxCapability.channelMode,
+                        aptx_data.channelMode)) {
+    return true;
+  }
+  LOG(WARNING) << __func__
+               << ": Unsupported CodecSpecific=" << codec_specific.toString();
+  return false;
+}
+
+bool BluetoothAudioCodecs::IsOffloadAptxHdConfigurationValid(
+    const CodecConfiguration::CodecSpecific& codec_specific) {
+  if (codec_specific.getTag() !=
+      CodecConfiguration::CodecSpecific::aptxConfig) {
+    LOG(WARNING) << __func__
+                 << ": Invalid CodecSpecific=" << codec_specific.toString();
+    return false;
+  }
+  const AptxConfiguration aptx_data =
+      codec_specific.get<CodecConfiguration::CodecSpecific::aptxConfig>();
+
+  if (ContainedInVector(kDefaultOffloadAptxHdCapability.sampleRateHz,
+                        aptx_data.sampleRateHz) &&
+      ContainedInVector(kDefaultOffloadAptxHdCapability.bitsPerSample,
+                        aptx_data.bitsPerSample) &&
+      ContainedInVector(kDefaultOffloadAptxHdCapability.channelMode,
+                        aptx_data.channelMode)) {
+    return true;
+  }
+  LOG(WARNING) << __func__
+               << ": Unsupported CodecSpecific=" << codec_specific.toString();
+  return false;
+}
+
+bool BluetoothAudioCodecs::IsOffloadLc3ConfigurationValid(
+    const CodecConfiguration::CodecSpecific& codec_specific) {
+  if (codec_specific.getTag() != CodecConfiguration::CodecSpecific::lc3Config) {
+    LOG(WARNING) << __func__
+                 << ": Invalid CodecSpecific=" << codec_specific.toString();
+    return false;
+  }
+  const Lc3Configuration lc3_data =
+      codec_specific.get<CodecConfiguration::CodecSpecific::lc3Config>();
+
+  if (ContainedInVector(kDefaultA2dpOffloadLc3Capability.samplingFrequencyHz,
+                        lc3_data.samplingFrequencyHz) &&
+      ContainedInVector(kDefaultA2dpOffloadLc3Capability.frameDurationUs,
+                        lc3_data.frameDurationUs) &&
+      ContainedInVector(kDefaultA2dpOffloadLc3Capability.channelMode,
+                        lc3_data.channelMode)) {
+    return true;
+  }
+  LOG(WARNING) << __func__
+               << ": Unsupported CodecSpecific=" << codec_specific.toString();
+  return false;
+}
+
+bool BluetoothAudioCodecs::IsOffloadLeAudioConfigurationValid(
+    const SessionType& session_type, const LeAudioConfiguration&) {
+  if (session_type !=
+          SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
+      session_type !=
+          SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH &&
+      session_type !=
+          SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
+    return false;
+  }
+  return true;
+}
+
+std::vector<PcmCapabilities>
+BluetoothAudioCodecs::GetSoftwarePcmCapabilities() {
+  return {kDefaultSoftwarePcmCapabilities};
+}
+
+std::vector<CodecCapabilities>
+BluetoothAudioCodecs::GetA2dpOffloadCodecCapabilities(
+    const SessionType& session_type) {
+  if (session_type != SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
+      session_type != SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+    return {};
+  }
+  std::vector<CodecCapabilities> offload_a2dp_codec_capabilities =
+      kDefaultOffloadA2dpCodecCapabilities;
+  for (auto& codec_capability : offload_a2dp_codec_capabilities) {
+    switch (codec_capability.codecType) {
+      case CodecType::SBC:
+        codec_capability.capabilities
+            .set<CodecCapabilities::Capabilities::sbcCapabilities>(
+                kDefaultOffloadSbcCapability);
+        break;
+      case CodecType::AAC:
+        codec_capability.capabilities
+            .set<CodecCapabilities::Capabilities::aacCapabilities>(
+                kDefaultOffloadAacCapability);
+        break;
+      case CodecType::LDAC:
+        codec_capability.capabilities
+            .set<CodecCapabilities::Capabilities::ldacCapabilities>(
+                kDefaultOffloadLdacCapability);
+        break;
+      case CodecType::APTX:
+        codec_capability.capabilities
+            .set<CodecCapabilities::Capabilities::aptxCapabilities>(
+                kDefaultOffloadAptxCapability);
+        break;
+      case CodecType::APTX_HD:
+        codec_capability.capabilities
+            .set<CodecCapabilities::Capabilities::aptxCapabilities>(
+                kDefaultOffloadAptxHdCapability);
+        break;
+      case CodecType::LC3:
+        codec_capability.capabilities
+            .set<CodecCapabilities::Capabilities::lc3Capabilities>(
+                kDefaultA2dpOffloadLc3Capability);
+        break;
+      case CodecType::UNKNOWN:
+      case CodecType::VENDOR:
+      case CodecType::APTX_ADAPTIVE:
+        break;
+    }
+  }
+  return offload_a2dp_codec_capabilities;
+}
+
+bool BluetoothAudioCodecs::IsSoftwarePcmConfigurationValid(
+    const PcmConfiguration& pcm_config) {
+  if (ContainedInVector(kDefaultSoftwarePcmCapabilities.sampleRateHz,
+                        pcm_config.sampleRateHz) &&
+      ContainedInVector(kDefaultSoftwarePcmCapabilities.bitsPerSample,
+                        pcm_config.bitsPerSample) &&
+      ContainedInVector(kDefaultSoftwarePcmCapabilities.channelMode,
+                        pcm_config.channelMode)
+      // data interval is not checked for now
+      // && pcm_config.dataIntervalUs != 0
+  ) {
+    return true;
+  }
+  LOG(WARNING) << __func__
+               << ": Unsupported CodecSpecific=" << pcm_config.toString();
+  return false;
+}
+
+bool BluetoothAudioCodecs::IsOffloadCodecConfigurationValid(
+    const SessionType& session_type, const CodecConfiguration& codec_config) {
+  if (session_type != SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
+      session_type != SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+    LOG(ERROR) << __func__
+               << ": Invalid SessionType=" << toString(session_type);
+    return false;
+  }
+  const CodecConfiguration::CodecSpecific& codec_specific = codec_config.config;
+  switch (codec_config.codecType) {
+    case CodecType::SBC:
+      if (IsOffloadSbcConfigurationValid(codec_specific)) {
+        return true;
+      }
+      break;
+    case CodecType::AAC:
+      if (IsOffloadAacConfigurationValid(codec_specific)) {
+        return true;
+      }
+      break;
+    case CodecType::LDAC:
+      if (IsOffloadLdacConfigurationValid(codec_specific)) {
+        return true;
+      }
+      break;
+    case CodecType::APTX:
+      if (IsOffloadAptxConfigurationValid(codec_specific)) {
+        return true;
+      }
+      break;
+    case CodecType::APTX_HD:
+      if (IsOffloadAptxHdConfigurationValid(codec_specific)) {
+        return true;
+      }
+      break;
+    case CodecType::LC3:
+      if (IsOffloadLc3ConfigurationValid(codec_specific)) {
+        return true;
+      }
+      break;
+    case CodecType::APTX_ADAPTIVE:
+    case CodecType::UNKNOWN:
+    case CodecType::VENDOR:
+      break;
+  }
+  return false;
+}
+
+UnicastCapability composeUnicastLc3Capability(
+    AudioLocation audioLocation, uint8_t deviceCnt, uint8_t channelCount,
+    const Lc3Capabilities& capability) {
+  return {
+      .codecType = CodecType::LC3,
+      .supportedChannel = audioLocation,
+      .deviceCount = deviceCnt,
+      .channelCountPerDevice = channelCount,
+      .leAudioCodecCapabilities =
+          UnicastCapability::LeAudioCodecCapabilities(capability),
+  };
+}
+
+std::vector<LeAudioCodecCapabilitiesSetting>
+BluetoothAudioCodecs::GetLeAudioOffloadCodecCapabilities(
+    const SessionType& session_type) {
+  if (session_type !=
+          SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
+      session_type !=
+          SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH &&
+      session_type !=
+          SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
+    return std::vector<LeAudioCodecCapabilitiesSetting>(0);
+  }
+
+  if (kDefaultOffloadLeAudioCapabilities.empty()) {
+    for (auto [audioLocation, deviceCnt, channelCount] :
+         supportedDeviceSetting) {
+      for (auto capability : supportedLc3CapabilityList) {
+        UnicastCapability lc3Capability = composeUnicastLc3Capability(
+            audioLocation, deviceCnt, channelCount, capability);
+        UnicastCapability lc3MonoDecodeCapability =
+            composeUnicastLc3Capability(monoAudio, 1, 1, capability);
+
+        // Adds the capability for encode only
+        kDefaultOffloadLeAudioCapabilities.push_back(
+            {.unicastEncodeCapability = lc3Capability,
+             .unicastDecodeCapability = kInvalidUnicastCapability,
+             .broadcastCapability = kInvalidBroadcastCapability});
+
+        // Adds the capability for decode only
+        kDefaultOffloadLeAudioCapabilities.push_back(
+            {.unicastEncodeCapability = kInvalidUnicastCapability,
+             .unicastDecodeCapability = lc3Capability,
+             .broadcastCapability = kInvalidBroadcastCapability});
+
+        // Adds the capability for the case that encode and decode exist at the
+        // same time
+        kDefaultOffloadLeAudioCapabilities.push_back(
+            {.unicastEncodeCapability = lc3Capability,
+             .unicastDecodeCapability = lc3MonoDecodeCapability,
+             .broadcastCapability = kInvalidBroadcastCapability});
+      }
+    }
+  }
+
+  return kDefaultOffloadLeAudioCapabilities;
+}
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.h b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.h
new file mode 100644
index 0000000..0259a7e
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.h
@@ -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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/bluetooth/audio/CodecCapabilities.h>
+#include <aidl/android/hardware/bluetooth/audio/CodecConfiguration.h>
+#include <aidl/android/hardware/bluetooth/audio/Lc3Configuration.h>
+#include <aidl/android/hardware/bluetooth/audio/LeAudioCodecCapabilitiesSetting.h>
+#include <aidl/android/hardware/bluetooth/audio/LeAudioConfiguration.h>
+#include <aidl/android/hardware/bluetooth/audio/PcmCapabilities.h>
+#include <aidl/android/hardware/bluetooth/audio/PcmConfiguration.h>
+#include <aidl/android/hardware/bluetooth/audio/SessionType.h>
+
+#include <vector>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+class BluetoothAudioCodecs {
+ public:
+  static std::vector<PcmCapabilities> GetSoftwarePcmCapabilities();
+  static std::vector<CodecCapabilities> GetA2dpOffloadCodecCapabilities(
+      const SessionType& session_type);
+
+  static bool IsSoftwarePcmConfigurationValid(
+      const PcmConfiguration& pcm_config);
+  static bool IsOffloadCodecConfigurationValid(
+      const SessionType& session_type, const CodecConfiguration& codec_config);
+
+  static bool IsOffloadLeAudioConfigurationValid(
+      const SessionType& session_type, const LeAudioConfiguration&);
+
+  static std::vector<LeAudioCodecCapabilitiesSetting>
+  GetLeAudioOffloadCodecCapabilities(const SessionType& session_type);
+
+ private:
+  template <typename T>
+  struct identity {
+    typedef T type;
+  };
+  template <class T>
+  static bool ContainedInVector(const std::vector<T>& vector,
+                                const typename identity<T>::type& target);
+  template <class T>
+  static bool ContainedInBitmask(const T& bitmask, const T& target);
+  static bool IsSingleBit(uint32_t bitmasks, uint32_t bitfield);
+  static bool IsOffloadSbcConfigurationValid(
+      const CodecConfiguration::CodecSpecific& codec_specific);
+  static bool IsOffloadAacConfigurationValid(
+      const CodecConfiguration::CodecSpecific& codec_specific);
+  static bool IsOffloadLdacConfigurationValid(
+      const CodecConfiguration::CodecSpecific& codec_specific);
+  static bool IsOffloadAptxConfigurationValid(
+      const CodecConfiguration::CodecSpecific& codec_specific);
+  static bool IsOffloadAptxHdConfigurationValid(
+      const CodecConfiguration::CodecSpecific& codec_specific);
+  static bool IsOffloadLc3ConfigurationValid(
+      const CodecConfiguration::CodecSpecific& codec_specific);
+};
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
new file mode 100644
index 0000000..3214bf2
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
@@ -0,0 +1,618 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <sys/types.h>
+#define LOG_TAG "BTAudioSessionAidl"
+
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <android/binder_manager.h>
+
+#include "BluetoothAudioSession.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+static constexpr int kFmqSendTimeoutMs = 1000;  // 1000 ms timeout for sending
+static constexpr int kFmqReceiveTimeoutMs =
+    1000;                               // 1000 ms timeout for receiving
+static constexpr int kWritePollMs = 1;  // polled non-blocking interval
+static constexpr int kReadPollMs = 1;   // polled non-blocking interval
+
+BluetoothAudioSession::BluetoothAudioSession(const SessionType& session_type)
+    : session_type_(session_type), stack_iface_(nullptr), data_mq_(nullptr) {}
+
+/***
+ *
+ * Callback methods
+ *
+ ***/
+
+void BluetoothAudioSession::OnSessionStarted(
+    const std::shared_ptr<IBluetoothAudioPort> stack_iface,
+    const DataMQDesc* mq_desc, const AudioConfiguration& audio_config,
+    const std::vector<LatencyMode>& latency_modes) {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  if (stack_iface == nullptr) {
+    LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
+               << ", IBluetoothAudioPort Invalid";
+  } else if (!UpdateAudioConfig(audio_config)) {
+    LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
+               << ", AudioConfiguration=" << audio_config.toString()
+               << " Invalid";
+  } else if (!UpdateDataPath(mq_desc)) {
+    LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
+               << " MqDescriptor Invalid";
+    audio_config_ = nullptr;
+  } else {
+    stack_iface_ = stack_iface;
+    latency_modes_ = latency_modes;
+    LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+              << ", AudioConfiguration=" << audio_config.toString();
+    ReportSessionStatus();
+  }
+}
+
+void BluetoothAudioSession::OnSessionEnded() {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  bool toggled = IsSessionReady();
+  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
+  audio_config_ = nullptr;
+  stack_iface_ = nullptr;
+  UpdateDataPath(nullptr);
+  if (toggled) {
+    ReportSessionStatus();
+  }
+}
+
+/***
+ *
+ * Util methods
+ *
+ ***/
+
+const AudioConfiguration BluetoothAudioSession::GetAudioConfig() {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  if (!IsSessionReady()) {
+    switch (session_type_) {
+      case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
+      case SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH:
+        return AudioConfiguration(CodecConfiguration{});
+      case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
+      case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
+        return AudioConfiguration(LeAudioConfiguration{});
+      case SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
+        return AudioConfiguration(LeAudioBroadcastConfiguration{});
+      default:
+        return AudioConfiguration(PcmConfiguration{});
+    }
+  }
+  return *audio_config_;
+}
+
+void BluetoothAudioSession::ReportAudioConfigChanged(
+    const AudioConfiguration& audio_config) {
+  if (session_type_ !=
+          SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
+      session_type_ !=
+          SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+    return;
+  }
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
+  if (observers_.empty()) {
+    LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
+                 << " has NO port state observer";
+    return;
+  }
+  for (auto& observer : observers_) {
+    uint16_t cookie = observer.first;
+    std::shared_ptr<struct PortStatusCallbacks> cb = observer.second;
+    LOG(INFO) << __func__ << " for SessionType=" << toString(session_type_)
+              << ", bluetooth_audio=0x"
+              << ::android::base::StringPrintf("%04x", cookie);
+    if (cb->audio_configuration_changed_cb_ != nullptr) {
+      cb->audio_configuration_changed_cb_(cookie);
+    }
+  }
+}
+
+bool BluetoothAudioSession::IsSessionReady() {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+
+  bool is_mq_valid =
+      (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+       session_type_ ==
+           SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+       session_type_ ==
+           SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
+       session_type_ ==
+           SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+       session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
+       (data_mq_ != nullptr && data_mq_->isValid()));
+  return stack_iface_ != nullptr && is_mq_valid && audio_config_ != nullptr;
+}
+
+/***
+ *
+ * Status callback methods
+ *
+ ***/
+
+uint16_t BluetoothAudioSession::RegisterStatusCback(
+    const PortStatusCallbacks& callbacks) {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  uint16_t cookie = ObserversCookieGetInitValue(session_type_);
+  uint16_t cookie_upper_bound = ObserversCookieGetUpperBound(session_type_);
+
+  while (cookie < cookie_upper_bound) {
+    if (observers_.find(cookie) == observers_.end()) {
+      break;
+    }
+    ++cookie;
+  }
+  if (cookie >= cookie_upper_bound) {
+    LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
+               << " has " << observers_.size()
+               << " observers already (No Resource)";
+    return kObserversCookieUndefined;
+  }
+  std::shared_ptr<PortStatusCallbacks> cb =
+      std::make_shared<PortStatusCallbacks>();
+  *cb = callbacks;
+  observers_[cookie] = cb;
+  return cookie;
+}
+
+void BluetoothAudioSession::UnregisterStatusCback(uint16_t cookie) {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  if (observers_.erase(cookie) != 1) {
+    LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
+                 << " no such provider=0x"
+                 << ::android::base::StringPrintf("%04x", cookie);
+  }
+}
+
+/***
+ *
+ * Stream methods
+ *
+ ***/
+
+bool BluetoothAudioSession::StartStream(bool is_low_latency) {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  if (!IsSessionReady()) {
+    LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
+               << " has NO session";
+    return false;
+  }
+  auto hal_retval = stack_iface_->startStream(is_low_latency);
+  if (!hal_retval.isOk()) {
+    LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
+                 << toString(session_type_) << " failed";
+    return false;
+  }
+  return true;
+}
+
+bool BluetoothAudioSession::SuspendStream() {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  if (!IsSessionReady()) {
+    LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
+               << " has NO session";
+    return false;
+  }
+  auto hal_retval = stack_iface_->suspendStream();
+  if (!hal_retval.isOk()) {
+    LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
+                 << toString(session_type_) << " failed";
+    return false;
+  }
+  return true;
+}
+
+void BluetoothAudioSession::StopStream() {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  if (!IsSessionReady()) {
+    return;
+  }
+  auto hal_retval = stack_iface_->stopStream();
+  if (!hal_retval.isOk()) {
+    LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
+                 << toString(session_type_) << " failed";
+  }
+}
+
+/***
+ *
+ * Private methods
+ *
+ ***/
+
+bool BluetoothAudioSession::UpdateDataPath(const DataMQDesc* mq_desc) {
+  if (mq_desc == nullptr) {
+    // usecase of reset by nullptr
+    data_mq_ = nullptr;
+    return true;
+  }
+  std::unique_ptr<DataMQ> temp_mq;
+  temp_mq.reset(new DataMQ(*mq_desc));
+  if (!temp_mq || !temp_mq->isValid()) {
+    data_mq_ = nullptr;
+    return false;
+  }
+  data_mq_ = std::move(temp_mq);
+  return true;
+}
+
+bool BluetoothAudioSession::UpdateAudioConfig(
+    const AudioConfiguration& audio_config) {
+  bool is_software_session =
+      (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
+       session_type_ == SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH ||
+       session_type_ == SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH ||
+       session_type_ == SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH ||
+       session_type_ ==
+           SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH ||
+       session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH);
+  bool is_offload_a2dp_session =
+      (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+       session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH);
+  bool is_offload_le_audio_session =
+      (session_type_ ==
+           SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+       session_type_ ==
+           SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
+  auto audio_config_tag = audio_config.getTag();
+  bool is_software_audio_config =
+      (is_software_session &&
+       audio_config_tag == AudioConfiguration::pcmConfig);
+  bool is_a2dp_offload_audio_config =
+      (is_offload_a2dp_session &&
+       audio_config_tag == AudioConfiguration::a2dpConfig);
+  bool is_le_audio_offload_audio_config =
+      (is_offload_le_audio_session &&
+       audio_config_tag == AudioConfiguration::leAudioConfig);
+  if (!is_software_audio_config && !is_a2dp_offload_audio_config &&
+      !is_le_audio_offload_audio_config) {
+    return false;
+  }
+  audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
+  return true;
+}
+
+void BluetoothAudioSession::ReportSessionStatus() {
+  // This is locked already by OnSessionStarted / OnSessionEnded
+  if (observers_.empty()) {
+    LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+              << " has NO port state observer";
+    return;
+  }
+  for (auto& observer : observers_) {
+    uint16_t cookie = observer.first;
+    std::shared_ptr<PortStatusCallbacks> callback = observer.second;
+    LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+              << " notify to bluetooth_audio=0x"
+              << ::android::base::StringPrintf("%04x", cookie);
+    callback->session_changed_cb_(cookie);
+  }
+}
+
+/***
+ *
+ * PCM methods
+ *
+ ***/
+
+size_t BluetoothAudioSession::OutWritePcmData(const void* buffer,
+                                              size_t bytes) {
+  if (buffer == nullptr || bytes <= 0) {
+    return 0;
+  }
+  size_t total_written = 0;
+  int timeout_ms = kFmqSendTimeoutMs;
+  do {
+    std::unique_lock<std::recursive_mutex> lock(mutex_);
+    if (!IsSessionReady()) {
+      break;
+    }
+    size_t num_bytes_to_write = data_mq_->availableToWrite();
+    if (num_bytes_to_write) {
+      if (num_bytes_to_write > (bytes - total_written)) {
+        num_bytes_to_write = bytes - total_written;
+      }
+
+      if (!data_mq_->write(
+              static_cast<const MQDataType*>(buffer) + total_written,
+              num_bytes_to_write)) {
+        LOG(ERROR) << "FMQ datapath writing " << total_written << "/" << bytes
+                   << " failed";
+        return total_written;
+      }
+      total_written += num_bytes_to_write;
+    } else if (timeout_ms >= kWritePollMs) {
+      lock.unlock();
+      usleep(kWritePollMs * 1000);
+      timeout_ms -= kWritePollMs;
+    } else {
+      LOG(DEBUG) << "Data " << total_written << "/" << bytes << " overflow "
+                 << (kFmqSendTimeoutMs - timeout_ms) << " ms";
+      return total_written;
+    }
+  } while (total_written < bytes);
+  return total_written;
+}
+
+size_t BluetoothAudioSession::InReadPcmData(void* buffer, size_t bytes) {
+  if (buffer == nullptr || bytes <= 0) {
+    return 0;
+  }
+  size_t total_read = 0;
+  int timeout_ms = kFmqReceiveTimeoutMs;
+  do {
+    std::unique_lock<std::recursive_mutex> lock(mutex_);
+    if (!IsSessionReady()) {
+      break;
+    }
+    size_t num_bytes_to_read = data_mq_->availableToRead();
+    if (num_bytes_to_read) {
+      if (num_bytes_to_read > (bytes - total_read)) {
+        num_bytes_to_read = bytes - total_read;
+      }
+      if (!data_mq_->read(static_cast<MQDataType*>(buffer) + total_read,
+                          num_bytes_to_read)) {
+        LOG(ERROR) << "FMQ datapath reading " << total_read << "/" << bytes
+                   << " failed";
+        return total_read;
+      }
+      total_read += num_bytes_to_read;
+    } else if (timeout_ms >= kReadPollMs) {
+      lock.unlock();
+      usleep(kReadPollMs * 1000);
+      timeout_ms -= kReadPollMs;
+      continue;
+    } else {
+      LOG(DEBUG) << "Data " << total_read << "/" << bytes << " overflow "
+                 << (kFmqReceiveTimeoutMs - timeout_ms) << " ms";
+      return total_read;
+    }
+  } while (total_read < bytes);
+  return total_read;
+}
+
+/***
+ *
+ * Other methods
+ *
+ ***/
+
+void BluetoothAudioSession::ReportControlStatus(bool start_resp,
+                                                BluetoothAudioStatus status) {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  if (observers_.empty()) {
+    LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
+                 << " has NO port state observer";
+    return;
+  }
+  for (auto& observer : observers_) {
+    uint16_t cookie = observer.first;
+    std::shared_ptr<PortStatusCallbacks> callback = observer.second;
+    LOG(INFO) << __func__ << " - status=" << toString(status)
+              << " for SessionType=" << toString(session_type_)
+              << ", bluetooth_audio=0x"
+              << ::android::base::StringPrintf("%04x", cookie)
+              << (start_resp ? " started" : " suspended");
+    callback->control_result_cb_(cookie, start_resp, status);
+  }
+}
+
+void BluetoothAudioSession::ReportLowLatencyModeAllowedChanged(bool allowed) {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  low_latency_allowed_ = allowed;
+  if (observers_.empty()) {
+    LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
+                 << " has NO port state observer";
+    return;
+  }
+  for (auto& observer : observers_) {
+    uint16_t cookie = observer.first;
+    std::shared_ptr<PortStatusCallbacks> callback = observer.second;
+    LOG(INFO) << __func__
+              << " - allowed=" << (allowed ? " allowed" : " disallowed");
+    if (callback->low_latency_mode_allowed_cb_ != nullptr) {
+      callback->low_latency_mode_allowed_cb_(cookie, allowed);
+    }
+  }
+}
+
+bool BluetoothAudioSession::GetPresentationPosition(
+    PresentationPosition& presentation_position) {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  if (!IsSessionReady()) {
+    LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
+               << " has NO session";
+    return false;
+  }
+  bool retval = false;
+
+  if (!stack_iface_->getPresentationPosition(&presentation_position).isOk()) {
+    LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
+                 << toString(session_type_) << " failed";
+    return false;
+  }
+  return retval;
+}
+
+void BluetoothAudioSession::UpdateSourceMetadata(
+    const struct source_metadata& source_metadata) {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  if (!IsSessionReady()) {
+    LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
+               << " has NO session";
+    return;
+  }
+
+  ssize_t track_count = source_metadata.track_count;
+  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << ","
+            << track_count << " track(s)";
+  if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
+      session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+      session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH ||
+      session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+    return;
+  }
+
+  SourceMetadata hal_source_metadata;
+  hal_source_metadata.tracks.resize(track_count);
+  for (int i = 0; i < track_count; i++) {
+    hal_source_metadata.tracks[i].usage =
+        static_cast<media::audio::common::AudioUsage>(
+            source_metadata.tracks[i].usage);
+    hal_source_metadata.tracks[i].contentType =
+        static_cast<media::audio::common::AudioContentType>(
+            source_metadata.tracks[i].content_type);
+    hal_source_metadata.tracks[i].gain = source_metadata.tracks[i].gain;
+    LOG(VERBOSE) << __func__ << " - SessionType=" << toString(session_type_)
+                 << ", usage=" << toString(hal_source_metadata.tracks[i].usage)
+                 << ", content="
+                 << toString(hal_source_metadata.tracks[i].contentType)
+                 << ", gain=" << hal_source_metadata.tracks[i].gain;
+  }
+
+  auto hal_retval = stack_iface_->updateSourceMetadata(hal_source_metadata);
+  if (!hal_retval.isOk()) {
+    LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
+                 << toString(session_type_) << " failed";
+  }
+}
+
+void BluetoothAudioSession::UpdateSinkMetadata(
+    const struct sink_metadata& sink_metadata) {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  if (!IsSessionReady()) {
+    LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
+               << " has NO session";
+    return;
+  }
+
+  ssize_t track_count = sink_metadata.track_count;
+  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << ","
+            << track_count << " track(s)";
+  if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
+      session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+      session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH ||
+      session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+    return;
+  }
+
+  SinkMetadata hal_sink_metadata;
+  hal_sink_metadata.tracks.resize(track_count);
+  for (int i = 0; i < track_count; i++) {
+    hal_sink_metadata.tracks[i].source =
+        static_cast<media::audio::common::AudioSource>(
+            sink_metadata.tracks[i].source);
+    hal_sink_metadata.tracks[i].gain = sink_metadata.tracks[i].gain;
+    LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+              << ", source=" << sink_metadata.tracks[i].source
+              << ", dest_device=" << sink_metadata.tracks[i].dest_device
+              << ", gain=" << sink_metadata.tracks[i].gain
+              << ", dest_device_address="
+              << sink_metadata.tracks[i].dest_device_address;
+  }
+
+  auto hal_retval = stack_iface_->updateSinkMetadata(hal_sink_metadata);
+  if (!hal_retval.isOk()) {
+    LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
+                 << toString(session_type_) << " failed";
+  }
+}
+
+std::vector<LatencyMode> BluetoothAudioSession::GetSupportedLatencyModes() {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  if (!IsSessionReady()) {
+    LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
+               << " has NO session";
+    return std::vector<LatencyMode>();
+  }
+  if (low_latency_allowed_) return latency_modes_;
+  std::vector<LatencyMode> modes;
+  for (LatencyMode mode : latency_modes_) {
+    if (mode == LatencyMode::LOW_LATENCY)
+      // ignore those low latency mode if Bluetooth stack doesn't allow
+      continue;
+    modes.push_back(mode);
+  }
+  return modes;
+}
+
+void BluetoothAudioSession::SetLatencyMode(const LatencyMode& latency_mode) {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  if (!IsSessionReady()) {
+    LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
+               << " has NO session";
+    return;
+  }
+
+  auto hal_retval = stack_iface_->setLatencyMode(latency_mode);
+  if (!hal_retval.isOk()) {
+    LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
+                 << toString(session_type_) << " failed";
+  }
+}
+
+bool BluetoothAudioSession::IsAidlAvailable() {
+  if (is_aidl_checked) return is_aidl_available;
+  is_aidl_available =
+      (AServiceManager_checkService(
+           kDefaultAudioProviderFactoryInterface.c_str()) != nullptr);
+  is_aidl_checked = true;
+  return is_aidl_available;
+}
+
+/***
+ *
+ * BluetoothAudioSessionInstance
+ *
+ ***/
+std::mutex BluetoothAudioSessionInstance::mutex_;
+std::unordered_map<SessionType, std::shared_ptr<BluetoothAudioSession>>
+    BluetoothAudioSessionInstance::sessions_map_;
+
+std::shared_ptr<BluetoothAudioSession>
+BluetoothAudioSessionInstance::GetSessionInstance(
+    const SessionType& session_type) {
+  std::lock_guard<std::mutex> guard(mutex_);
+
+  if (!sessions_map_.empty()) {
+    auto entry = sessions_map_.find(session_type);
+    if (entry != sessions_map_.end()) {
+      return entry->second;
+    }
+  }
+  std::shared_ptr<BluetoothAudioSession> session_ptr =
+      std::make_shared<BluetoothAudioSession>(session_type);
+  sessions_map_[session_type] = session_ptr;
+  return session_ptr;
+}
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.h b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.h
new file mode 100644
index 0000000..5bf17bd
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.h
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/common/SinkMetadata.h>
+#include <aidl/android/hardware/audio/common/SourceMetadata.h>
+#include <aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.h>
+#include <aidl/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.h>
+#include <aidl/android/hardware/bluetooth/audio/LatencyMode.h>
+#include <aidl/android/hardware/bluetooth/audio/SessionType.h>
+#include <fmq/AidlMessageQueue.h>
+#include <hardware/audio.h>
+
+#include <mutex>
+#include <unordered_map>
+#include <vector>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+using ::aidl::android::hardware::common::fmq::MQDescriptor;
+using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using ::android::AidlMessageQueue;
+
+using ::aidl::android::hardware::audio::common::SinkMetadata;
+using ::aidl::android::hardware::audio::common::SourceMetadata;
+
+using MQDataType = int8_t;
+using MQDataMode = SynchronizedReadWrite;
+using DataMQ = AidlMessageQueue<MQDataType, MQDataMode>;
+using DataMQDesc =
+    ::aidl::android::hardware::common::fmq::MQDescriptor<MQDataType,
+                                                         MQDataMode>;
+
+static constexpr uint16_t kObserversCookieSize = 0x0010;  // 0x0000 ~ 0x000f
+static constexpr uint16_t kObserversCookieUndefined =
+    (static_cast<uint16_t>(SessionType::UNKNOWN) << 8 & 0xff00);
+inline SessionType ObserversCookieGetSessionType(uint16_t cookie) {
+  return static_cast<SessionType>(cookie >> 8 & 0x00ff);
+}
+inline uint16_t ObserversCookieGetInitValue(SessionType session_type) {
+  return (static_cast<uint16_t>(session_type) << 8 & 0xff00);
+}
+inline uint16_t ObserversCookieGetUpperBound(SessionType session_type) {
+  return (static_cast<uint16_t>(session_type) << 8 & 0xff00) +
+         kObserversCookieSize;
+}
+
+/***
+ * This presents the callbacks of started / suspended and session changed,
+ * and the bluetooth_audio module uses to receive the status notification
+ ***/
+struct PortStatusCallbacks {
+  /***
+   * control_result_cb_ - when the Bluetooth stack reports results of
+   * streamStarted or streamSuspended, the BluetoothAudioProvider will invoke
+   * this callback to report to the bluetooth_audio module.
+   * @param: cookie - indicates which bluetooth_audio output should handle
+   * @param: start_resp - this report is for startStream or not
+   * @param: status - the result of startStream
+   ***/
+  std::function<void(uint16_t cookie, bool start_resp,
+                     BluetoothAudioStatus status)>
+      control_result_cb_;
+  /***
+   * session_changed_cb_ - when the Bluetooth stack start / end session, the
+   * BluetoothAudioProvider will invoke this callback to notify to the
+   * bluetooth_audio module.
+   * @param: cookie - indicates which bluetooth_audio output should handle
+   ***/
+  std::function<void(uint16_t cookie)> session_changed_cb_;
+  /***
+   * audio_configuration_changed_cb_ - when the Bluetooth stack change the audio
+   * configuration, the BluetoothAudioProvider will invoke this callback to
+   * notify to the bluetooth_audio module.
+   * @param: cookie - indicates which bluetooth_audio output should handle
+   ***/
+  std::function<void(uint16_t cookie)> audio_configuration_changed_cb_;
+  /***
+   * low_latency_mode_allowed_cb_ - when the Bluetooth stack low latency mode
+   * allowed or disallowed, the BluetoothAudioProvider will invoke
+   * this callback to report to the bluetooth_audio module.
+   * @param: cookie - indicates which bluetooth_audio output should handle
+   * @param: allowed - indicates if low latency mode is allowed
+   ***/
+  std::function<void(uint16_t cookie, bool allowed)>
+      low_latency_mode_allowed_cb_;
+};
+
+class BluetoothAudioSession {
+ public:
+  BluetoothAudioSession(const SessionType& session_type);
+
+  /***
+   * The function helps to check if this session is ready or not
+   * @return: true if the Bluetooth stack has started the specified session
+   ***/
+  bool IsSessionReady();
+
+  /***
+   * The report function is used to report that the Bluetooth stack has started
+   * this session without any failure, and will invoke session_changed_cb_ to
+   * notify those registered bluetooth_audio outputs
+   ***/
+  void OnSessionStarted(const std::shared_ptr<IBluetoothAudioPort> stack_iface,
+                        const DataMQDesc* mq_desc,
+                        const AudioConfiguration& audio_config,
+                        const std::vector<LatencyMode>& latency_modes);
+
+  /***
+   * The report function is used to report that the Bluetooth stack has ended
+   * the session, and will invoke session_changed_cb_ to notify registered
+   * bluetooth_audio outputs
+   ***/
+  void OnSessionEnded();
+
+  /***
+   * The report function is used to report that the Bluetooth stack has notified
+   * the result of startStream or suspendStream, and will invoke
+   * control_result_cb_ to notify registered bluetooth_audio outputs
+   ***/
+  void ReportControlStatus(bool start_resp, BluetoothAudioStatus status);
+
+  /***
+   * The control function helps the bluetooth_audio module to register
+   * PortStatusCallbacks
+   * @return: cookie - the assigned number to this bluetooth_audio output
+   ***/
+  uint16_t RegisterStatusCback(const PortStatusCallbacks& cbacks);
+
+  /***
+   * The control function helps the bluetooth_audio module to unregister
+   * PortStatusCallbacks
+   * @param: cookie - indicates which bluetooth_audio output is
+   ***/
+  void UnregisterStatusCback(uint16_t cookie);
+
+  /***
+   * The control function is for the bluetooth_audio module to get the current
+   * AudioConfiguration
+   ***/
+  const AudioConfiguration GetAudioConfig();
+
+  /***
+   * The report function is used to report that the Bluetooth stack has notified
+   * the audio configuration changed, and will invoke
+   * audio_configuration_changed_cb_ to notify registered bluetooth_audio
+   * outputs
+   ***/
+  void ReportAudioConfigChanged(const AudioConfiguration& audio_config);
+
+  /***
+   * The report function is used to report that the Bluetooth stack has notified
+   * the low latency mode allowed changed, and will invoke
+   * low_latency_mode_allowed_changed_cb to notify registered bluetooth_audio
+   * outputs
+   ***/
+  void ReportLowLatencyModeAllowedChanged(bool allowed);
+  /***
+   * Those control functions are for the bluetooth_audio module to start,
+   * suspend, stop stream, to check position, and to update metadata.
+   ***/
+  bool StartStream(bool low_latency);
+  bool SuspendStream();
+  void StopStream();
+  bool GetPresentationPosition(PresentationPosition& presentation_position);
+  void UpdateSourceMetadata(const struct source_metadata& source_metadata);
+  void UpdateSinkMetadata(const struct sink_metadata& sink_metadata);
+
+  std::vector<LatencyMode> GetSupportedLatencyModes();
+  void SetLatencyMode(const LatencyMode& latency_mode);
+
+  // The control function writes stream to FMQ
+  size_t OutWritePcmData(const void* buffer, size_t bytes);
+  // The control function read stream from FMQ
+  size_t InReadPcmData(void* buffer, size_t bytes);
+
+  // Return if IBluetoothAudioProviderFactory implementation existed
+  static bool IsAidlAvailable();
+
+ private:
+  // using recursive_mutex to allow hwbinder to re-enter again.
+  std::recursive_mutex mutex_;
+  SessionType session_type_;
+
+  // audio control path to use for both software and offloading
+  std::shared_ptr<IBluetoothAudioPort> stack_iface_;
+  // audio data path (FMQ) for software encoding
+  std::unique_ptr<DataMQ> data_mq_;
+  // audio data configuration for both software and offloading
+  std::unique_ptr<AudioConfiguration> audio_config_;
+  std::vector<LatencyMode> latency_modes_;
+  bool low_latency_allowed_ = true;
+
+  // saving those registered bluetooth_audio's callbacks
+  std::unordered_map<uint16_t, std::shared_ptr<struct PortStatusCallbacks>>
+      observers_;
+
+  bool UpdateDataPath(const DataMQDesc* mq_desc);
+  bool UpdateAudioConfig(const AudioConfiguration& audio_config);
+  // invoking the registered session_changed_cb_
+  void ReportSessionStatus();
+
+  static inline std::atomic<bool> is_aidl_checked = false;
+  static inline std::atomic<bool> is_aidl_available = false;
+  static inline const std::string kDefaultAudioProviderFactoryInterface =
+      std::string() + IBluetoothAudioProviderFactory::descriptor + "/default";
+};
+
+class BluetoothAudioSessionInstance {
+ public:
+  // The API is to fetch the specified session of A2DP / Hearing Aid
+  static std::shared_ptr<BluetoothAudioSession> GetSessionInstance(
+      const SessionType& session_type);
+
+ private:
+  static std::mutex mutex_;
+  static std::unordered_map<SessionType, std::shared_ptr<BluetoothAudioSession>>
+      sessions_map_;
+};
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionControl.h b/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionControl.h
new file mode 100644
index 0000000..0782c82
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionControl.h
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "BluetoothAudioSession.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+class BluetoothAudioSessionControl {
+ public:
+  /***
+   * The control API helps to check if session is ready or not
+   * @return: true if the Bluetooth stack has started th specified session
+   ***/
+  static bool IsSessionReady(const SessionType& session_type) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      return session_ptr->IsSessionReady();
+    }
+
+    return false;
+  }
+
+  /***
+   * The control API helps the bluetooth_audio module to register
+   * PortStatusCallbacks
+   * @return: cookie - the assigned number to this bluetooth_audio output
+   ***/
+  static uint16_t RegisterControlResultCback(
+      const SessionType& session_type, const PortStatusCallbacks& cbacks) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      return session_ptr->RegisterStatusCback(cbacks);
+    }
+    return kObserversCookieUndefined;
+  }
+
+  /***
+   * The control API helps the bluetooth_audio module to unregister
+   * PortStatusCallbacks
+   * @param: cookie - indicates which bluetooth_audio output is
+   ***/
+  static void UnregisterControlResultCback(const SessionType& session_type,
+                                           uint16_t cookie) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      session_ptr->UnregisterStatusCback(cookie);
+    }
+  }
+
+  /***
+   * The control API for the bluetooth_audio module to get current
+   * AudioConfiguration
+   ***/
+  static const AudioConfiguration GetAudioConfig(
+      const SessionType& session_type) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      return session_ptr->GetAudioConfig();
+    }
+    switch (session_type) {
+      case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
+      case SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH:
+        return AudioConfiguration(CodecConfiguration{});
+      case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
+      case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
+        return AudioConfiguration(LeAudioConfiguration{});
+      case SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
+        return AudioConfiguration(LeAudioBroadcastConfiguration{});
+      default:
+        return AudioConfiguration(PcmConfiguration{});
+    }
+  }
+
+  /***
+   * Those control APIs for the bluetooth_audio module to start / suspend /
+  stop
+   * stream, to check position, and to update metadata.
+  ***/
+  static bool StartStream(const SessionType& session_type,
+                          bool low_latency = false) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      return session_ptr->StartStream(low_latency);
+    }
+    return false;
+  }
+
+  static bool SuspendStream(const SessionType& session_type) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      return session_ptr->SuspendStream();
+    }
+    return false;
+  }
+
+  static void StopStream(const SessionType& session_type) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      session_ptr->StopStream();
+    }
+  }
+
+  static bool GetPresentationPosition(
+      const SessionType& session_type,
+      PresentationPosition& presentation_position) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      return session_ptr->GetPresentationPosition(presentation_position);
+    }
+    return false;
+  }
+
+  static void UpdateSourceMetadata(
+      const SessionType& session_type,
+      const struct source_metadata& source_metadata) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      session_ptr->UpdateSourceMetadata(source_metadata);
+    }
+  }
+
+  static void UpdateSinkMetadata(const SessionType& session_type,
+                                 const struct sink_metadata& sink_metadata) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      session_ptr->UpdateSinkMetadata(sink_metadata);
+    }
+  }
+
+  static std::vector<LatencyMode> GetSupportedLatencyModes(
+      const SessionType& session_type) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      return session_ptr->GetSupportedLatencyModes();
+    }
+    return std::vector<LatencyMode>();
+  }
+
+  static void SetLatencyMode(const SessionType& session_type,
+                             const LatencyMode& latency_mode) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      session_ptr->SetLatencyMode(latency_mode);
+    }
+  }
+
+  /***
+   * The control API writes stream to FMQ
+   ***/
+  static size_t OutWritePcmData(const SessionType& session_type,
+                                const void* buffer, size_t bytes) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      return session_ptr->OutWritePcmData(buffer, bytes);
+    }
+    return 0;
+  }
+
+  /***
+   * The control API reads stream from FMQ
+   ***/
+  static size_t InReadPcmData(const SessionType& session_type, void* buffer,
+                              size_t bytes) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      return session_ptr->InReadPcmData(buffer, bytes);
+    }
+    return 0;
+  }
+};
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionReport.h b/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionReport.h
new file mode 100644
index 0000000..0350259
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionReport.h
@@ -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.
+ */
+
+#pragma once
+
+#include "BluetoothAudioSession.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+class BluetoothAudioSessionReport {
+ public:
+  /***
+   * The API reports the Bluetooth stack has started the session, and will
+   * inform registered bluetooth_audio outputs
+   ***/
+  static void OnSessionStarted(
+      const SessionType& session_type,
+      const std::shared_ptr<IBluetoothAudioPort> host_iface,
+      const DataMQDesc* data_mq, const AudioConfiguration& audio_config,
+      const std::vector<LatencyMode>& latency_modes) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      session_ptr->OnSessionStarted(host_iface, data_mq, audio_config,
+                                    latency_modes);
+    }
+  }
+
+  /***
+   * The API reports the Bluetooth stack has ended the session, and will
+   * inform registered bluetooth_audio outputs
+   ***/
+  static void OnSessionEnded(const SessionType& session_type) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      session_ptr->OnSessionEnded();
+    }
+  }
+
+  /***
+   * The API reports the Bluetooth stack has replied the result of startStream
+   * or suspendStream, and will inform registered bluetooth_audio outputs
+   ***/
+  static void ReportControlStatus(const SessionType& session_type,
+                                  const bool& start_resp,
+                                  BluetoothAudioStatus status) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      session_ptr->ReportControlStatus(start_resp, status);
+    }
+  }
+  /***
+   * The API reports the Bluetooth stack has replied the changed of the audio
+   * configuration, and will inform registered bluetooth_audio outputs
+   ***/
+  static void ReportAudioConfigChanged(const SessionType& session_type,
+                                       const AudioConfiguration& audio_config) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      session_ptr->ReportAudioConfigChanged(audio_config);
+    }
+  }
+  /***
+   * The API reports the Bluetooth stack has replied the changed of the low
+   * latency audio allowed, and will inform registered bluetooth_audio outputs
+   ***/
+  static void ReportLowLatencyModeAllowedChanged(
+    const SessionType& session_type, bool allowed) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      session_ptr->ReportLowLatencyModeAllowedChanged(allowed);
+    }
+  }
+};
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware.cpp b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware.cpp
new file mode 100644
index 0000000..a4664f1
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware.cpp
@@ -0,0 +1,632 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "BtAudioNakahara"
+
+#include <aidl/android/hardware/bluetooth/audio/AudioConfiguration.h>
+#include <aidl/android/hardware/bluetooth/audio/BluetoothAudioStatus.h>
+#include <aidl/android/hardware/bluetooth/audio/SessionType.h>
+#include <android-base/logging.h>
+
+#include <functional>
+#include <unordered_map>
+
+#include "../aidl_session/BluetoothAudioSession.h"
+#include "../aidl_session/BluetoothAudioSessionControl.h"
+#include "HidlToAidlMiddleware_2_0.h"
+#include "HidlToAidlMiddleware_2_1.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+using HidlStatus = ::android::hardware::bluetooth::audio::V2_0::Status;
+using PcmConfig_2_0 =
+    ::android::hardware::bluetooth::audio::V2_0::PcmParameters;
+using SampleRate_2_0 = ::android::hardware::bluetooth::audio::V2_0::SampleRate;
+using ChannelMode_2_0 =
+    ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
+using BitsPerSample_2_0 =
+    ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
+using CodecConfig_2_0 =
+    ::android::hardware::bluetooth::audio::V2_0::CodecConfiguration;
+using CodecType_2_0 = ::android::hardware::bluetooth::audio::V2_0::CodecType;
+using SbcConfig_2_0 =
+    ::android::hardware::bluetooth::audio::V2_0::SbcParameters;
+using AacConfig_2_0 =
+    ::android::hardware::bluetooth::audio::V2_0::AacParameters;
+using LdacConfig_2_0 =
+    ::android::hardware::bluetooth::audio::V2_0::LdacParameters;
+using AptxConfig_2_0 =
+    ::android::hardware::bluetooth::audio::V2_0::AptxParameters;
+using SbcAllocMethod_2_0 =
+    ::android::hardware::bluetooth::audio::V2_0::SbcAllocMethod;
+using SbcBlockLength_2_0 =
+    ::android::hardware::bluetooth::audio::V2_0::SbcBlockLength;
+using SbcChannelMode_2_0 =
+    ::android::hardware::bluetooth::audio::V2_0::SbcChannelMode;
+using SbcNumSubbands_2_0 =
+    ::android::hardware::bluetooth::audio::V2_0::SbcNumSubbands;
+using AacObjectType_2_0 =
+    ::android::hardware::bluetooth::audio::V2_0::AacObjectType;
+using AacVarBitRate_2_0 =
+    ::android::hardware::bluetooth::audio::V2_0::AacVariableBitRate;
+using LdacChannelMode_2_0 =
+    ::android::hardware::bluetooth::audio::V2_0::LdacChannelMode;
+using LdacQualityIndex_2_0 =
+    ::android::hardware::bluetooth::audio::V2_0::LdacQualityIndex;
+
+using PcmConfig_2_1 =
+    ::android::hardware::bluetooth::audio::V2_1::PcmParameters;
+using SampleRate_2_1 = ::android::hardware::bluetooth::audio::V2_1::SampleRate;
+using Lc3CodecConfig_2_1 =
+    ::android::hardware::bluetooth::audio::V2_1::Lc3CodecConfiguration;
+using Lc3Config_2_1 =
+    ::android::hardware::bluetooth::audio::V2_1::Lc3Parameters;
+using Lc3FrameDuration_2_1 =
+    ::android::hardware::bluetooth::audio::V2_1::Lc3FrameDuration;
+
+std::mutex legacy_callback_lock;
+std::unordered_map<
+    SessionType,
+    std::unordered_map<uint16_t, std::shared_ptr<PortStatusCallbacks_2_0>>>
+    legacy_callback_table;
+
+const static std::unordered_map<SessionType_2_1, SessionType>
+    session_type_2_1_to_aidl_map{
+        {SessionType_2_1::A2DP_SOFTWARE_ENCODING_DATAPATH,
+         SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH},
+        {SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH,
+         SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH},
+        {SessionType_2_1::HEARING_AID_SOFTWARE_ENCODING_DATAPATH,
+         SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH},
+        {SessionType_2_1::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH,
+         SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH},
+        {SessionType_2_1::LE_AUDIO_SOFTWARE_DECODED_DATAPATH,
+         SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH},
+        {SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
+         SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH},
+        {SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH,
+         SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH},
+    };
+
+const static std::unordered_map<int32_t, SampleRate_2_1>
+    sample_rate_to_hidl_2_1_map{
+        {44100, SampleRate_2_1::RATE_44100},
+        {48000, SampleRate_2_1::RATE_48000},
+        {88200, SampleRate_2_1::RATE_88200},
+        {96000, SampleRate_2_1::RATE_96000},
+        {176400, SampleRate_2_1::RATE_176400},
+        {192000, SampleRate_2_1::RATE_192000},
+        {16000, SampleRate_2_1::RATE_16000},
+        {24000, SampleRate_2_1::RATE_24000},
+        {8000, SampleRate_2_1::RATE_8000},
+        {32000, SampleRate_2_1::RATE_32000},
+    };
+
+const static std::unordered_map<CodecType, CodecType_2_0>
+    codec_type_to_hidl_2_0_map{
+        {CodecType::UNKNOWN, CodecType_2_0::UNKNOWN},
+        {CodecType::SBC, CodecType_2_0::SBC},
+        {CodecType::AAC, CodecType_2_0::AAC},
+        {CodecType::APTX, CodecType_2_0::APTX},
+        {CodecType::APTX_HD, CodecType_2_0::APTX_HD},
+        {CodecType::LDAC, CodecType_2_0::LDAC},
+        {CodecType::LC3, CodecType_2_0::UNKNOWN},
+    };
+
+const static std::unordered_map<SbcChannelMode, SbcChannelMode_2_0>
+    sbc_channel_mode_to_hidl_2_0_map{
+        {SbcChannelMode::UNKNOWN, SbcChannelMode_2_0::UNKNOWN},
+        {SbcChannelMode::JOINT_STEREO, SbcChannelMode_2_0::JOINT_STEREO},
+        {SbcChannelMode::STEREO, SbcChannelMode_2_0::STEREO},
+        {SbcChannelMode::DUAL, SbcChannelMode_2_0::DUAL},
+        {SbcChannelMode::MONO, SbcChannelMode_2_0::MONO},
+    };
+
+const static std::unordered_map<int8_t, SbcBlockLength_2_0>
+    sbc_block_length_to_hidl_map{
+        {4, SbcBlockLength_2_0::BLOCKS_4},
+        {8, SbcBlockLength_2_0::BLOCKS_8},
+        {12, SbcBlockLength_2_0::BLOCKS_12},
+        {16, SbcBlockLength_2_0::BLOCKS_16},
+    };
+
+const static std::unordered_map<int8_t, SbcNumSubbands_2_0>
+    sbc_subbands_to_hidl_map{
+        {4, SbcNumSubbands_2_0::SUBBAND_4},
+        {8, SbcNumSubbands_2_0::SUBBAND_8},
+    };
+
+const static std::unordered_map<SbcAllocMethod, SbcAllocMethod_2_0>
+    sbc_alloc_method_to_hidl_map{
+        {SbcAllocMethod::ALLOC_MD_S, SbcAllocMethod_2_0::ALLOC_MD_S},
+        {SbcAllocMethod::ALLOC_MD_L, SbcAllocMethod_2_0::ALLOC_MD_L},
+    };
+
+const static std::unordered_map<AacObjectType, AacObjectType_2_0>
+    aac_object_type_to_hidl_map{
+        {AacObjectType::MPEG2_LC, AacObjectType_2_0::MPEG2_LC},
+        {AacObjectType::MPEG4_LC, AacObjectType_2_0::MPEG4_LC},
+        {AacObjectType::MPEG4_LTP, AacObjectType_2_0::MPEG4_LTP},
+        {AacObjectType::MPEG4_SCALABLE, AacObjectType_2_0::MPEG4_SCALABLE},
+    };
+
+const static std::unordered_map<LdacChannelMode, LdacChannelMode_2_0>
+    ldac_channel_mode_to_hidl_map{
+        {LdacChannelMode::UNKNOWN, LdacChannelMode_2_0::UNKNOWN},
+        {LdacChannelMode::STEREO, LdacChannelMode_2_0::STEREO},
+        {LdacChannelMode::DUAL, LdacChannelMode_2_0::DUAL},
+        {LdacChannelMode::MONO, LdacChannelMode_2_0::MONO},
+    };
+
+const static std::unordered_map<LdacQualityIndex, LdacQualityIndex_2_0>
+    ldac_qindex_to_hidl_map{
+        {LdacQualityIndex::HIGH, LdacQualityIndex_2_0::QUALITY_HIGH},
+        {LdacQualityIndex::MID, LdacQualityIndex_2_0::QUALITY_MID},
+        {LdacQualityIndex::LOW, LdacQualityIndex_2_0::QUALITY_LOW},
+        {LdacQualityIndex::ABR, LdacQualityIndex_2_0::QUALITY_ABR},
+    };
+
+inline SessionType from_session_type_2_1(
+    const SessionType_2_1& session_type_hidl) {
+  auto it = session_type_2_1_to_aidl_map.find(session_type_hidl);
+  if (it != session_type_2_1_to_aidl_map.end()) return it->second;
+  return SessionType::UNKNOWN;
+}
+
+inline SessionType from_session_type_2_0(
+    const SessionType_2_0& session_type_hidl) {
+  return from_session_type_2_1(static_cast<SessionType_2_1>(session_type_hidl));
+}
+
+inline HidlStatus to_hidl_status(const BluetoothAudioStatus& status) {
+  switch (status) {
+    case BluetoothAudioStatus::SUCCESS:
+      return HidlStatus::SUCCESS;
+    case BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION:
+      return HidlStatus::UNSUPPORTED_CODEC_CONFIGURATION;
+    default:
+      return HidlStatus::FAILURE;
+  }
+}
+
+inline SampleRate_2_1 to_hidl_sample_rate_2_1(const int32_t sample_rate_hz) {
+  auto it = sample_rate_to_hidl_2_1_map.find(sample_rate_hz);
+  if (it != sample_rate_to_hidl_2_1_map.end()) return it->second;
+  return SampleRate_2_1::RATE_UNKNOWN;
+}
+
+inline SampleRate_2_0 to_hidl_sample_rate_2_0(const int32_t sample_rate_hz) {
+  auto it = sample_rate_to_hidl_2_1_map.find(sample_rate_hz);
+  if (it != sample_rate_to_hidl_2_1_map.end())
+    return static_cast<SampleRate_2_0>(it->second);
+  return SampleRate_2_0::RATE_UNKNOWN;
+}
+
+inline BitsPerSample_2_0 to_hidl_bits_per_sample(const int8_t bit_per_sample) {
+  switch (bit_per_sample) {
+    case 16:
+      return BitsPerSample_2_0::BITS_16;
+    case 24:
+      return BitsPerSample_2_0::BITS_24;
+    case 32:
+      return BitsPerSample_2_0::BITS_32;
+    default:
+      return BitsPerSample_2_0::BITS_UNKNOWN;
+  }
+}
+
+inline ChannelMode_2_0 to_hidl_channel_mode(const ChannelMode channel_mode) {
+  switch (channel_mode) {
+    case ChannelMode::MONO:
+      return ChannelMode_2_0::MONO;
+    case ChannelMode::STEREO:
+      return ChannelMode_2_0::STEREO;
+    default:
+      return ChannelMode_2_0::UNKNOWN;
+  }
+}
+
+inline PcmConfig_2_0 to_hidl_pcm_config_2_0(
+    const PcmConfiguration& pcm_config) {
+  PcmConfig_2_0 hidl_pcm_config;
+  hidl_pcm_config.sampleRate = to_hidl_sample_rate_2_0(pcm_config.sampleRateHz);
+  hidl_pcm_config.channelMode = to_hidl_channel_mode(pcm_config.channelMode);
+  hidl_pcm_config.bitsPerSample =
+      to_hidl_bits_per_sample(pcm_config.bitsPerSample);
+  return hidl_pcm_config;
+}
+
+inline CodecType_2_0 to_hidl_codec_type_2_0(const CodecType codec_type) {
+  auto it = codec_type_to_hidl_2_0_map.find(codec_type);
+  if (it != codec_type_to_hidl_2_0_map.end()) return it->second;
+  return CodecType_2_0::UNKNOWN;
+}
+
+inline SbcConfig_2_0 to_hidl_sbc_config(const SbcConfiguration sbc_config) {
+  SbcConfig_2_0 hidl_sbc_config;
+  hidl_sbc_config.minBitpool = sbc_config.minBitpool;
+  hidl_sbc_config.maxBitpool = sbc_config.maxBitpool;
+  hidl_sbc_config.sampleRate = to_hidl_sample_rate_2_0(sbc_config.sampleRateHz);
+  hidl_sbc_config.bitsPerSample =
+      to_hidl_bits_per_sample(sbc_config.bitsPerSample);
+  if (sbc_channel_mode_to_hidl_2_0_map.find(sbc_config.channelMode) !=
+      sbc_channel_mode_to_hidl_2_0_map.end()) {
+    hidl_sbc_config.channelMode =
+        sbc_channel_mode_to_hidl_2_0_map.at(sbc_config.channelMode);
+  }
+  if (sbc_block_length_to_hidl_map.find(sbc_config.blockLength) !=
+      sbc_block_length_to_hidl_map.end()) {
+    hidl_sbc_config.blockLength =
+        sbc_block_length_to_hidl_map.at(sbc_config.blockLength);
+  }
+  if (sbc_subbands_to_hidl_map.find(sbc_config.numSubbands) !=
+      sbc_subbands_to_hidl_map.end()) {
+    hidl_sbc_config.numSubbands =
+        sbc_subbands_to_hidl_map.at(sbc_config.numSubbands);
+  }
+  if (sbc_alloc_method_to_hidl_map.find(sbc_config.allocMethod) !=
+      sbc_alloc_method_to_hidl_map.end()) {
+    hidl_sbc_config.allocMethod =
+        sbc_alloc_method_to_hidl_map.at(sbc_config.allocMethod);
+  }
+  return hidl_sbc_config;
+}
+
+inline AacConfig_2_0 to_hidl_aac_config(const AacConfiguration aac_config) {
+  AacConfig_2_0 hidl_aac_config;
+  hidl_aac_config.sampleRate = to_hidl_sample_rate_2_0(aac_config.sampleRateHz);
+  hidl_aac_config.bitsPerSample =
+      to_hidl_bits_per_sample(aac_config.bitsPerSample);
+  hidl_aac_config.channelMode = to_hidl_channel_mode(aac_config.channelMode);
+  if (aac_object_type_to_hidl_map.find(aac_config.objectType) !=
+      aac_object_type_to_hidl_map.end()) {
+    hidl_aac_config.objectType =
+        aac_object_type_to_hidl_map.at(aac_config.objectType);
+  }
+  hidl_aac_config.variableBitRateEnabled = aac_config.variableBitRateEnabled
+                                               ? AacVarBitRate_2_0::ENABLED
+                                               : AacVarBitRate_2_0::DISABLED;
+  return hidl_aac_config;
+}
+
+inline LdacConfig_2_0 to_hidl_ldac_config(const LdacConfiguration ldac_config) {
+  LdacConfig_2_0 hidl_ldac_config;
+  hidl_ldac_config.sampleRate =
+      to_hidl_sample_rate_2_0(ldac_config.sampleRateHz);
+  hidl_ldac_config.bitsPerSample =
+      to_hidl_bits_per_sample(ldac_config.bitsPerSample);
+  if (ldac_channel_mode_to_hidl_map.find(ldac_config.channelMode) !=
+      ldac_channel_mode_to_hidl_map.end()) {
+    hidl_ldac_config.channelMode =
+        ldac_channel_mode_to_hidl_map.at(ldac_config.channelMode);
+  }
+  if (ldac_qindex_to_hidl_map.find(ldac_config.qualityIndex) !=
+      ldac_qindex_to_hidl_map.end()) {
+    hidl_ldac_config.qualityIndex =
+        ldac_qindex_to_hidl_map.at(ldac_config.qualityIndex);
+  }
+  return hidl_ldac_config;
+}
+
+inline AptxConfig_2_0 to_hidl_aptx_config(const AptxConfiguration aptx_config) {
+  AptxConfig_2_0 hidl_aptx_config;
+  hidl_aptx_config.sampleRate =
+      to_hidl_sample_rate_2_0(aptx_config.sampleRateHz);
+  hidl_aptx_config.bitsPerSample =
+      to_hidl_bits_per_sample(aptx_config.bitsPerSample);
+  hidl_aptx_config.channelMode = to_hidl_channel_mode(aptx_config.channelMode);
+  return hidl_aptx_config;
+}
+
+inline CodecConfig_2_0 to_hidl_codec_config_2_0(
+    const CodecConfiguration& codec_config) {
+  CodecConfig_2_0 hidl_codec_config;
+  hidl_codec_config.codecType = to_hidl_codec_type_2_0(codec_config.codecType);
+  hidl_codec_config.encodedAudioBitrate =
+      static_cast<uint32_t>(codec_config.encodedAudioBitrate);
+  hidl_codec_config.peerMtu = static_cast<uint32_t>(codec_config.peerMtu);
+  hidl_codec_config.isScmstEnabled = codec_config.isScmstEnabled;
+  switch (codec_config.config.getTag()) {
+    case CodecConfiguration::CodecSpecific::sbcConfig:
+      hidl_codec_config.config.sbcConfig(to_hidl_sbc_config(
+          codec_config.config
+              .get<CodecConfiguration::CodecSpecific::sbcConfig>()));
+      break;
+    case CodecConfiguration::CodecSpecific::aacConfig:
+      hidl_codec_config.config.aacConfig(to_hidl_aac_config(
+          codec_config.config
+              .get<CodecConfiguration::CodecSpecific::aacConfig>()));
+      break;
+    case CodecConfiguration::CodecSpecific::ldacConfig:
+      hidl_codec_config.config.ldacConfig(to_hidl_ldac_config(
+          codec_config.config
+              .get<CodecConfiguration::CodecSpecific::ldacConfig>()));
+      break;
+    case CodecConfiguration::CodecSpecific::aptxConfig:
+      hidl_codec_config.config.aptxConfig(to_hidl_aptx_config(
+          codec_config.config
+              .get<CodecConfiguration::CodecSpecific::aptxConfig>()));
+      break;
+    default:
+      break;
+  }
+  return hidl_codec_config;
+}
+
+inline AudioConfig_2_0 to_hidl_audio_config_2_0(
+    const AudioConfiguration& audio_config) {
+  AudioConfig_2_0 hidl_audio_config;
+  if (audio_config.getTag() == AudioConfiguration::pcmConfig) {
+    hidl_audio_config.pcmConfig(to_hidl_pcm_config_2_0(
+        audio_config.get<AudioConfiguration::pcmConfig>()));
+  } else if (audio_config.getTag() == AudioConfiguration::a2dpConfig) {
+    hidl_audio_config.codecConfig(to_hidl_codec_config_2_0(
+        audio_config.get<AudioConfiguration::a2dpConfig>()));
+  }
+  return hidl_audio_config;
+}
+
+inline PcmConfig_2_1 to_hidl_pcm_config_2_1(
+    const PcmConfiguration& pcm_config) {
+  PcmConfig_2_1 hidl_pcm_config;
+  hidl_pcm_config.sampleRate = to_hidl_sample_rate_2_1(pcm_config.sampleRateHz);
+  hidl_pcm_config.channelMode = to_hidl_channel_mode(pcm_config.channelMode);
+  hidl_pcm_config.bitsPerSample =
+      to_hidl_bits_per_sample(pcm_config.bitsPerSample);
+  hidl_pcm_config.dataIntervalUs =
+      static_cast<uint32_t>(pcm_config.dataIntervalUs);
+  return hidl_pcm_config;
+}
+
+inline Lc3Config_2_1 to_hidl_lc3_config_2_1(
+    const Lc3Configuration& lc3_config) {
+  Lc3Config_2_1 hidl_lc3_config;
+  hidl_lc3_config.pcmBitDepth = to_hidl_bits_per_sample(lc3_config.pcmBitDepth);
+  hidl_lc3_config.samplingFrequency =
+      to_hidl_sample_rate_2_1(lc3_config.samplingFrequencyHz);
+  if (lc3_config.samplingFrequencyHz == 10000)
+    hidl_lc3_config.frameDuration = Lc3FrameDuration_2_1::DURATION_10000US;
+  else if (lc3_config.samplingFrequencyHz == 7500)
+    hidl_lc3_config.frameDuration = Lc3FrameDuration_2_1::DURATION_7500US;
+  hidl_lc3_config.octetsPerFrame =
+      static_cast<uint32_t>(lc3_config.octetsPerFrame);
+  hidl_lc3_config.blocksPerSdu = static_cast<uint32_t>(lc3_config.blocksPerSdu);
+  return hidl_lc3_config;
+}
+
+inline Lc3CodecConfig_2_1 to_hidl_leaudio_config_2_1(
+    const LeAudioConfiguration& unicast_config) {
+  Lc3CodecConfig_2_1 hidl_lc3_codec_config = {
+      .audioChannelAllocation = 0,
+  };
+  if (unicast_config.leAudioCodecConfig.getTag() ==
+      LeAudioCodecConfiguration::lc3Config) {
+    LOG(FATAL) << __func__ << ": unexpected codec type(vendor?)";
+  }
+  auto& le_codec_config = unicast_config.leAudioCodecConfig
+                              .get<LeAudioCodecConfiguration::lc3Config>();
+
+  hidl_lc3_codec_config.lc3Config = to_hidl_lc3_config_2_1(le_codec_config);
+
+  for (const auto& map : unicast_config.streamMap) {
+    hidl_lc3_codec_config.audioChannelAllocation |= map.audioChannelAllocation;
+  }
+  return hidl_lc3_codec_config;
+}
+
+inline Lc3CodecConfig_2_1 to_hidl_leaudio_broadcast_config_2_1(
+    const LeAudioBroadcastConfiguration& broadcast_config) {
+  Lc3CodecConfig_2_1 hidl_lc3_codec_config = {
+      .audioChannelAllocation = 0,
+  };
+  // NOTE: Broadcast is not officially supported in HIDL
+  if (broadcast_config.streamMap.empty()) {
+    return hidl_lc3_codec_config;
+  }
+  if (broadcast_config.streamMap[0].leAudioCodecConfig.getTag() !=
+      LeAudioCodecConfiguration::lc3Config) {
+    LOG(FATAL) << __func__ << ": unexpected codec type(vendor?)";
+  }
+  auto& le_codec_config =
+      broadcast_config.streamMap[0]
+          .leAudioCodecConfig.get<LeAudioCodecConfiguration::lc3Config>();
+  hidl_lc3_codec_config.lc3Config = to_hidl_lc3_config_2_1(le_codec_config);
+
+  for (const auto& map : broadcast_config.streamMap) {
+    hidl_lc3_codec_config.audioChannelAllocation |= map.audioChannelAllocation;
+  }
+  return hidl_lc3_codec_config;
+}
+
+inline AudioConfig_2_1 to_hidl_audio_config_2_1(
+    const AudioConfiguration& audio_config) {
+  AudioConfig_2_1 hidl_audio_config;
+  switch (audio_config.getTag()) {
+    case AudioConfiguration::pcmConfig:
+      hidl_audio_config.pcmConfig(to_hidl_pcm_config_2_1(
+          audio_config.get<AudioConfiguration::pcmConfig>()));
+      break;
+    case AudioConfiguration::a2dpConfig:
+      hidl_audio_config.codecConfig(to_hidl_codec_config_2_0(
+          audio_config.get<AudioConfiguration::a2dpConfig>()));
+      break;
+    case AudioConfiguration::leAudioConfig:
+      hidl_audio_config.leAudioCodecConfig(to_hidl_leaudio_config_2_1(
+          audio_config.get<AudioConfiguration::leAudioConfig>()));
+      break;
+    case AudioConfiguration::leAudioBroadcastConfig:
+      hidl_audio_config.leAudioCodecConfig(to_hidl_leaudio_broadcast_config_2_1(
+          audio_config.get<AudioConfiguration::leAudioBroadcastConfig>()));
+      break;
+  }
+  return hidl_audio_config;
+}
+
+/***
+ *
+ * 2.0
+ *
+ ***/
+
+bool HidlToAidlMiddleware_2_0::IsSessionReady(
+    const SessionType_2_0& session_type) {
+  return BluetoothAudioSessionControl::IsSessionReady(
+      from_session_type_2_0(session_type));
+}
+
+uint16_t HidlToAidlMiddleware_2_0::RegisterControlResultCback(
+    const SessionType_2_0& session_type,
+    const PortStatusCallbacks_2_0& cbacks) {
+  LOG(INFO) << __func__ << ": " << toString(session_type);
+  auto aidl_session_type = from_session_type_2_0(session_type);
+  // Pass the exact reference to the lambda
+  auto& session_legacy_callback_table =
+      legacy_callback_table[aidl_session_type];
+  PortStatusCallbacks aidl_callbacks{};
+  if (cbacks.control_result_cb_) {
+    aidl_callbacks.control_result_cb_ =
+        [&session_legacy_callback_table](uint16_t cookie, bool start_resp,
+                                         const BluetoothAudioStatus& status) {
+          if (session_legacy_callback_table.find(cookie) ==
+              session_legacy_callback_table.end()) {
+            LOG(ERROR) << __func__ << ": Unknown callback invoked!";
+            return;
+          }
+          auto& cback = session_legacy_callback_table[cookie];
+          cback->control_result_cb_(cookie, start_resp, to_hidl_status(status));
+        };
+  }
+  if (cbacks.session_changed_cb_) {
+    aidl_callbacks.session_changed_cb_ =
+        [&session_legacy_callback_table](uint16_t cookie) {
+          if (session_legacy_callback_table.find(cookie) ==
+              session_legacy_callback_table.end()) {
+            LOG(ERROR) << __func__ << ": Unknown callback invoked!";
+            return;
+          }
+          auto& cback = session_legacy_callback_table[cookie];
+          cback->session_changed_cb_(cookie);
+        };
+  };
+  auto cookie = BluetoothAudioSessionControl::RegisterControlResultCback(
+      aidl_session_type, aidl_callbacks);
+  {
+    std::lock_guard<std::mutex> guard(legacy_callback_lock);
+    session_legacy_callback_table[cookie] =
+        std::make_shared<PortStatusCallbacks_2_0>(cbacks);
+  }
+  return cookie;
+}
+
+void HidlToAidlMiddleware_2_0::UnregisterControlResultCback(
+    const SessionType_2_0& session_type, uint16_t cookie) {
+  LOG(INFO) << __func__ << ": " << toString(session_type);
+  auto aidl_session_type = from_session_type_2_0(session_type);
+  BluetoothAudioSessionControl::UnregisterControlResultCback(aidl_session_type,
+                                                             cookie);
+  auto& session_callback_table = legacy_callback_table[aidl_session_type];
+  if (session_callback_table.find(cookie) != session_callback_table.end()) {
+    std::lock_guard<std::mutex> guard(legacy_callback_lock);
+    session_callback_table.erase(cookie);
+  }
+}
+
+const AudioConfig_2_0 HidlToAidlMiddleware_2_0::GetAudioConfig(
+    const SessionType_2_0& session_type) {
+  return to_hidl_audio_config_2_0(BluetoothAudioSessionControl::GetAudioConfig(
+      from_session_type_2_0(session_type)));
+}
+
+bool HidlToAidlMiddleware_2_0::StartStream(
+    const SessionType_2_0& session_type) {
+  return BluetoothAudioSessionControl::StartStream(
+      from_session_type_2_0(session_type));
+}
+
+void HidlToAidlMiddleware_2_0::StopStream(const SessionType_2_0& session_type) {
+  return BluetoothAudioSessionControl::StopStream(
+      from_session_type_2_0(session_type));
+}
+
+bool HidlToAidlMiddleware_2_0::SuspendStream(
+    const SessionType_2_0& session_type) {
+  return BluetoothAudioSessionControl::SuspendStream(
+      from_session_type_2_0(session_type));
+}
+
+bool HidlToAidlMiddleware_2_0::GetPresentationPosition(
+    const SessionType_2_0& session_type, uint64_t* remote_delay_report_ns,
+    uint64_t* total_bytes_readed, timespec* data_position) {
+  PresentationPosition presentation_position;
+  auto ret_val = BluetoothAudioSessionControl::GetPresentationPosition(
+      from_session_type_2_0(session_type), presentation_position);
+  if (remote_delay_report_ns)
+    *remote_delay_report_ns = presentation_position.remoteDeviceAudioDelayNanos;
+  if (total_bytes_readed)
+    *total_bytes_readed = presentation_position.transmittedOctets;
+  if (data_position)
+    *data_position = {
+        .tv_sec = static_cast<__kernel_old_time_t>(
+            presentation_position.transmittedOctetsTimestamp.tvSec),
+        .tv_nsec = static_cast<long>(
+            presentation_position.transmittedOctetsTimestamp.tvNSec)};
+  return ret_val;
+}
+
+void HidlToAidlMiddleware_2_0::UpdateTracksMetadata(
+    const SessionType_2_0& session_type,
+    const struct source_metadata* source_metadata) {
+  return BluetoothAudioSessionControl::UpdateSourceMetadata(
+      from_session_type_2_0(session_type), *source_metadata);
+}
+
+size_t HidlToAidlMiddleware_2_0::OutWritePcmData(
+    const SessionType_2_0& session_type, const void* buffer, size_t bytes) {
+  return BluetoothAudioSessionControl::OutWritePcmData(
+      from_session_type_2_0(session_type), buffer, bytes);
+}
+
+size_t HidlToAidlMiddleware_2_0::InReadPcmData(
+    const SessionType_2_0& session_type, void* buffer, size_t bytes) {
+  return BluetoothAudioSessionControl::InReadPcmData(
+      from_session_type_2_0(session_type), buffer, bytes);
+}
+
+bool HidlToAidlMiddleware_2_0::IsAidlAvailable() {
+  return BluetoothAudioSession::IsAidlAvailable();
+}
+
+/***
+ *
+ * 2.1
+ *
+ ***/
+
+const AudioConfig_2_1 HidlToAidlMiddleware_2_1::GetAudioConfig(
+    const SessionType_2_1& session_type) {
+  return to_hidl_audio_config_2_1(BluetoothAudioSessionControl::GetAudioConfig(
+      from_session_type_2_1(session_type)));
+}
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_0.h b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_0.h
new file mode 100644
index 0000000..b124d8f
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_0.h
@@ -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.
+ */
+
+#include <android/hardware/bluetooth/audio/2.0/types.h>
+
+#include "../session/BluetoothAudioSession.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+using SessionType_2_0 =
+    ::android::hardware::bluetooth::audio::V2_0::SessionType;
+using PortStatusCallbacks_2_0 =
+    ::android::bluetooth::audio::PortStatusCallbacks;
+using AudioConfig_2_0 =
+    ::android::hardware::bluetooth::audio::V2_0::AudioConfiguration;
+
+class HidlToAidlMiddleware_2_0 {
+ public:
+  static bool IsAidlAvailable();
+
+  static bool IsSessionReady(const SessionType_2_0& session_type);
+
+  static uint16_t RegisterControlResultCback(
+      const SessionType_2_0& session_type,
+      const PortStatusCallbacks_2_0& cbacks);
+
+  static void UnregisterControlResultCback(const SessionType_2_0& session_type,
+                                           uint16_t cookie);
+
+  static const AudioConfig_2_0 GetAudioConfig(
+      const SessionType_2_0& session_type);
+
+  static bool StartStream(const SessionType_2_0& session_type);
+
+  static void StopStream(const SessionType_2_0& session_type);
+
+  static bool SuspendStream(const SessionType_2_0& session_type);
+
+  static bool GetPresentationPosition(const SessionType_2_0& session_type,
+                                      uint64_t* remote_delay_report_ns,
+                                      uint64_t* total_bytes_readed,
+                                      timespec* data_position);
+
+  static void UpdateTracksMetadata(
+      const SessionType_2_0& session_type,
+      const struct source_metadata* source_metadata);
+
+  static size_t OutWritePcmData(const SessionType_2_0& session_type,
+                                const void* buffer, size_t bytes);
+
+  static size_t InReadPcmData(const SessionType_2_0& session_type, void* buffer,
+                              size_t bytes);
+};
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_1.h b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_1.h
new file mode 100644
index 0000000..82dce96
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_1.h
@@ -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.
+ */
+
+#include <android/hardware/bluetooth/audio/2.1/types.h>
+
+#include "../session/BluetoothAudioSession.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+using SessionType_2_1 =
+    ::android::hardware::bluetooth::audio::V2_1::SessionType;
+using AudioConfig_2_1 =
+    ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration;
+
+class HidlToAidlMiddleware_2_1 {
+ public:
+  static const AudioConfig_2_1 GetAudioConfig(
+      const SessionType_2_1& session_type);
+};
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession.cpp b/bluetooth/audio/utils/session/BluetoothAudioSession.cpp
index 2f3ddaf..283952e 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSession.cpp
+++ b/bluetooth/audio/utils/session/BluetoothAudioSession.cpp
@@ -21,10 +21,13 @@
 #include <android-base/logging.h>
 #include <android-base/stringprintf.h>
 
+#include "../aidl_session/HidlToAidlMiddleware_2_0.h"
+
 namespace android {
 namespace bluetooth {
 namespace audio {
 
+using ::aidl::android::hardware::bluetooth::audio::HidlToAidlMiddleware_2_0;
 using ::android::hardware::audio::common::V5_0::AudioContentType;
 using ::android::hardware::audio::common::V5_0::AudioUsage;
 using ::android::hardware::audio::common::V5_0::PlaybackTrackMetadata;
@@ -149,6 +152,8 @@
 // The function helps to check if this session is ready or not
 // @return: true if the Bluetooth stack has started the specified session
 bool BluetoothAudioSession::IsSessionReady() {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_0::IsSessionReady(session_type_);
   std::lock_guard<std::recursive_mutex> guard(mutex_);
   bool dataMQ_valid =
       (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH ||
@@ -200,6 +205,9 @@
 // @return: cookie - the assigned number to this bluetooth_audio output
 uint16_t BluetoothAudioSession::RegisterStatusCback(
     const PortStatusCallbacks& cbacks) {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_0::RegisterControlResultCback(session_type_,
+                                                                cbacks);
   std::lock_guard<std::recursive_mutex> guard(mutex_);
   uint16_t cookie = ObserversCookieGetInitValue(session_type_);
   uint16_t cookie_upper_bound = ObserversCookieGetUpperBound(session_type_);
@@ -227,6 +235,9 @@
 // PortStatusCallbacks
 // @param: cookie - indicates which bluetooth_audio output is
 void BluetoothAudioSession::UnregisterStatusCback(uint16_t cookie) {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_0::UnregisterControlResultCback(session_type_,
+                                                                  cookie);
   std::lock_guard<std::recursive_mutex> guard(mutex_);
   if (observers_.erase(cookie) != 1) {
     LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
@@ -238,6 +249,9 @@
 // The control function is for the bluetooth_audio module to get the current
 // AudioConfiguration
 const AudioConfiguration& BluetoothAudioSession::GetAudioConfig() {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return (audio_config_ =
+                HidlToAidlMiddleware_2_0::GetAudioConfig(session_type_));
   std::lock_guard<std::recursive_mutex> guard(mutex_);
   if (IsSessionReady()) {
     return audio_config_;
@@ -251,6 +265,8 @@
 // Those control functions are for the bluetooth_audio module to start, suspend,
 // stop stream, to check position, and to update metadata.
 bool BluetoothAudioSession::StartStream() {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_0::StartStream(session_type_);
   std::lock_guard<std::recursive_mutex> guard(mutex_);
   if (!IsSessionReady()) {
     LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
@@ -267,6 +283,8 @@
 }
 
 bool BluetoothAudioSession::SuspendStream() {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_0::SuspendStream(session_type_);
   std::lock_guard<std::recursive_mutex> guard(mutex_);
   if (!IsSessionReady()) {
     LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
@@ -283,6 +301,8 @@
 }
 
 void BluetoothAudioSession::StopStream() {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_0::StopStream(session_type_);
   std::lock_guard<std::recursive_mutex> guard(mutex_);
   if (!IsSessionReady()) {
     return;
@@ -297,6 +317,10 @@
 bool BluetoothAudioSession::GetPresentationPosition(
     uint64_t* remote_delay_report_ns, uint64_t* total_bytes_readed,
     timespec* data_position) {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_0::GetPresentationPosition(
+        session_type_, remote_delay_report_ns, total_bytes_readed,
+        data_position);
   std::lock_guard<std::recursive_mutex> guard(mutex_);
   if (!IsSessionReady()) {
     LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
@@ -330,6 +354,9 @@
 
 void BluetoothAudioSession::UpdateTracksMetadata(
     const struct source_metadata* source_metadata) {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_0::UpdateTracksMetadata(session_type_,
+                                                          source_metadata);
   std::lock_guard<std::recursive_mutex> guard(mutex_);
   if (!IsSessionReady()) {
     LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
@@ -374,6 +401,9 @@
 // The control function writes stream to FMQ
 size_t BluetoothAudioSession::OutWritePcmData(const void* buffer,
                                               size_t bytes) {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_0::OutWritePcmData(session_type_, buffer,
+                                                     bytes);
   if (buffer == nullptr || !bytes) return 0;
   size_t totalWritten = 0;
   int ms_timeout = kFmqSendTimeoutMs;
@@ -407,6 +437,9 @@
 
 // The control function reads stream from FMQ
 size_t BluetoothAudioSession::InReadPcmData(void* buffer, size_t bytes) {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_0::InReadPcmData(session_type_, buffer,
+                                                   bytes);
   if (buffer == nullptr || !bytes) return 0;
   size_t totalRead = 0;
   int ms_timeout = kFmqReceiveTimeoutMs;
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession.h b/bluetooth/audio/utils/session/BluetoothAudioSession.h
index 83e20ad..3469cc0 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSession.h
+++ b/bluetooth/audio/utils/session/BluetoothAudioSession.h
@@ -80,6 +80,7 @@
 
 class BluetoothAudioSession {
   friend class BluetoothAudioSession_2_1;
+  friend class BluetoothAudioSession_2_2;
 
  private:
   // using recursive_mutex to allow hwbinder to re-enter agian.
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp b/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp
index 9d91196..276a291 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp
+++ b/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp
@@ -21,9 +21,14 @@
 #include <android-base/logging.h>
 #include <android-base/stringprintf.h>
 
+#include "../aidl_session/HidlToAidlMiddleware_2_0.h"
+#include "../aidl_session/HidlToAidlMiddleware_2_1.h"
+
 namespace android {
 namespace bluetooth {
 namespace audio {
+using ::aidl::android::hardware::bluetooth::audio::HidlToAidlMiddleware_2_0;
+using ::aidl::android::hardware::bluetooth::audio::HidlToAidlMiddleware_2_1;
 using SessionType_2_1 =
     ::android::hardware::bluetooth::audio::V2_1::SessionType;
 using SessionType_2_0 =
@@ -46,6 +51,19 @@
     return false;
   }
 }
+
+bool is_unsupported_2_1_session_type(
+    const ::android::hardware::bluetooth::audio::V2_1::SessionType&
+        session_type) {
+  if (session_type ==
+          SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+      session_type ==
+          SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+    return true;
+  } else {
+    return false;
+  }
+}
 }  // namespace
 
 BluetoothAudioSession_2_1::BluetoothAudioSession_2_1(
@@ -53,11 +71,13 @@
         session_type)
     : audio_session(BluetoothAudioSessionInstance::GetSessionInstance(
           static_cast<SessionType_2_0>(session_type))) {
-  if (is_2_0_session_type(session_type)) {
+  if (is_2_0_session_type(session_type) ||
+      is_unsupported_2_1_session_type(session_type)) {
     session_type_2_1_ = (SessionType_2_1::UNKNOWN);
   } else {
     session_type_2_1_ = (session_type);
   }
+  raw_session_type_ = session_type;
 }
 
 std::shared_ptr<BluetoothAudioSession>
@@ -69,6 +89,8 @@
 // AudioConfiguration
 const ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration
 BluetoothAudioSession_2_1::GetAudioConfig() {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_1::GetAudioConfig(raw_session_type_);
   std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
   if (audio_session->IsSessionReady()) {
     // If session is unknown it means it should be 2.0 type
@@ -80,7 +102,7 @@
     // pcmConfig only differs between 2.0 and 2.1 in AudioConfiguration
     if (fromConf.getDiscriminator() ==
         AudioConfiguration::hidl_discriminator::codecConfig) {
-      toConf.codecConfig() = fromConf.codecConfig();
+      toConf.codecConfig(fromConf.codecConfig());
     } else {
       toConf.pcmConfig() = {
           .sampleRate = static_cast<
@@ -110,7 +132,7 @@
            SessionType_2_1::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH ||
        session_type_2_1_ ==
            SessionType_2_1::LE_AUDIO_SOFTWARE_DECODED_DATAPATH);
-  bool is_offload_session =
+  bool is_offload_a2dp_session =
       (session_type_2_1_ == SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH);
   auto audio_config_discriminator = audio_config.getDiscriminator();
   bool is_software_audio_config =
@@ -118,12 +140,12 @@
        audio_config_discriminator ==
            ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration::
                hidl_discriminator::pcmConfig);
-  bool is_offload_audio_config =
-      (is_offload_session &&
+  bool is_a2dp_offload_audio_config =
+      (is_offload_a2dp_session &&
        audio_config_discriminator ==
            ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration::
                hidl_discriminator::codecConfig);
-  if (!is_software_audio_config && !is_offload_audio_config) {
+  if (!is_software_audio_config && !is_a2dp_offload_audio_config) {
     return false;
   }
   audio_config_2_1_ = audio_config;
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.h b/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.h
index 5a35153..e634064 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.h
+++ b/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.h
@@ -31,6 +31,7 @@
   std::shared_ptr<BluetoothAudioSession> audio_session;
 
   ::android::hardware::bluetooth::audio::V2_1::SessionType session_type_2_1_;
+  ::android::hardware::bluetooth::audio::V2_1::SessionType raw_session_type_;
 
   // audio data configuration for both software and offloading
   ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_1.cpp b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_1.cpp
index 8b0b0f7..c90ce6d 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_1.cpp
+++ b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_1.cpp
@@ -122,6 +122,21 @@
   return false;
 }
 
+bool IsOffloadLeAudioConfigurationValid(
+    const ::android::hardware::bluetooth::audio::V2_1::SessionType&
+        session_type,
+    const ::android::hardware::bluetooth::audio::V2_1::Lc3CodecConfiguration&) {
+
+  if (session_type != SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
+      session_type != SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+    return false;
+  }
+
+  //TODO: perform checks on le_audio_codec_config once we know supported parameters
+
+  return true;
+}
+
 }  // namespace audio
 }  // namespace bluetooth
 }  // namespace android
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_1.h b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_1.h
index 746d9c0..a52636c 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_1.h
+++ b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_1.h
@@ -41,6 +41,11 @@
     const ::android::hardware::bluetooth::audio::V2_0::CodecConfiguration&
         codec_config);
 
+bool IsOffloadLeAudioConfigurationValid(
+    const ::android::hardware::bluetooth::audio::V2_1::SessionType&
+        session_type,
+    const ::android::hardware::bluetooth::audio::V2_1::Lc3CodecConfiguration&
+        le_audio_codec_config);
 }  // namespace audio
 }  // namespace bluetooth
 }  // namespace android
diff --git a/boot/1.0/vts/functional/OWNERS b/boot/1.0/vts/functional/OWNERS
new file mode 100644
index 0000000..36e79be
--- /dev/null
+++ b/boot/1.0/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 30545
+dvander@google.com
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/vts/functional/OWNERS b/boot/1.1/vts/functional/OWNERS
new file mode 100644
index 0000000..36e79be
--- /dev/null
+++ b/boot/1.1/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 30545
+dvander@google.com
diff --git a/boot/aidl/Android.bp b/boot/aidl/Android.bp
new file mode 100644
index 0000000..b1a6be0
--- /dev/null
+++ b/boot/aidl/Android.bp
@@ -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.
+//
+
+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/broadcastradio/1.0/vts/functional/OWNERS b/broadcastradio/1.0/vts/functional/OWNERS
new file mode 100644
index 0000000..778c4a2
--- /dev/null
+++ b/broadcastradio/1.0/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 533946
+oscarazu@google.com
diff --git a/broadcastradio/1.1/vts/OWNERS b/broadcastradio/1.1/vts/OWNERS
index 7736681..2c21c25 100644
--- a/broadcastradio/1.1/vts/OWNERS
+++ b/broadcastradio/1.1/vts/OWNERS
@@ -1,8 +1,3 @@
-# Automotive team
-egranata@google.com
+# Bug component: 533946
+oscarazu@google.com
 keunyoung@google.com
-twasilczyk@google.com
-
-# VTS team
-yuexima@google.com
-yim@google.com
diff --git a/broadcastradio/1.1/vts/functional/Android.bp b/broadcastradio/1.1/vts/functional/Android.bp
index f0dfe96..0fb4eb0 100644
--- a/broadcastradio/1.1/vts/functional/Android.bp
+++ b/broadcastradio/1.1/vts/functional/Android.bp
@@ -26,6 +26,7 @@
 cc_test {
     name: "VtsHalBroadcastradioV1_1TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: ["VtsHalBroadcastradioV1_1TargetTest.cpp"],
     srcs: ["VtsHalBroadcastradioV1_1TargetTest.cpp"],
     static_libs: [
         "android.hardware.broadcastradio@1.0",
diff --git a/broadcastradio/2.0/default/Android.bp b/broadcastradio/2.0/default/Android.bp
index 870c944..38eeb15 100644
--- a/broadcastradio/2.0/default/Android.bp
+++ b/broadcastradio/2.0/default/Android.bp
@@ -25,6 +25,9 @@
 
 cc_binary {
     name: "android.hardware.broadcastradio@2.0-service",
+    vintf_fragments: [
+        "android.hardware.broadcastradio@2.0-service.xml",
+    ],
     init_rc: ["android.hardware.broadcastradio@2.0-service.rc"],
     vendor: true,
     relative_install_path: "hw",
@@ -41,7 +44,7 @@
         "TunerSession.cpp",
         "VirtualProgram.cpp",
         "VirtualRadio.cpp",
-        "service.cpp"
+        "service.cpp",
     ],
     static_libs: [
         "android.hardware.broadcastradio@common-utils-2x-lib",
diff --git a/broadcastradio/2.0/default/android.hardware.broadcastradio@2.0-service.rc b/broadcastradio/2.0/default/android.hardware.broadcastradio@2.0-service.rc
index dd8c9c6..d58ba53 100644
--- a/broadcastradio/2.0/default/android.hardware.broadcastradio@2.0-service.rc
+++ b/broadcastradio/2.0/default/android.hardware.broadcastradio@2.0-service.rc
@@ -1,5 +1,6 @@
 service broadcastradio-hal2 /vendor/bin/hw/android.hardware.broadcastradio@2.0-service
-    interface android.hardware.broadcastradio@2.0::IBroadcastRadio default
+    interface android.hardware.broadcastradio@2.0::IBroadcastRadio amfm
+    interface android.hardware.broadcastradio@2.0::IBroadcastRadio dab
     class hal
     user audioserver
     group audio
diff --git a/broadcastradio/2.0/default/android.hardware.broadcastradio@2.0-service.xml b/broadcastradio/2.0/default/android.hardware.broadcastradio@2.0-service.xml
new file mode 100644
index 0000000..97f2e4d
--- /dev/null
+++ b/broadcastradio/2.0/default/android.hardware.broadcastradio@2.0-service.xml
@@ -0,0 +1,12 @@
+<manifest version="1.0" type="device">
+    <hal format="hidl">
+        <name>android.hardware.broadcastradio</name>
+        <transport>hwbinder</transport>
+        <version>2.0</version>
+        <interface>
+            <name>IBroadcastRadio</name>
+            <instance>amfm</instance>
+            <instance>dab</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/broadcastradio/2.0/vts/functional/Android.bp b/broadcastradio/2.0/vts/functional/Android.bp
index e26486d..cb50c5e 100644
--- a/broadcastradio/2.0/vts/functional/Android.bp
+++ b/broadcastradio/2.0/vts/functional/Android.bp
@@ -26,6 +26,7 @@
 cc_test {
     name: "VtsHalBroadcastradioV2_0TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: ["VtsHalBroadcastradioV2_0TargetTest.cpp"],
     srcs: ["VtsHalBroadcastradioV2_0TargetTest.cpp"],
     static_libs: [
         "android.hardware.broadcastradio@2.0",
diff --git a/broadcastradio/2.0/vts/functional/OWNERS b/broadcastradio/2.0/vts/functional/OWNERS
new file mode 100644
index 0000000..2c21c25
--- /dev/null
+++ b/broadcastradio/2.0/vts/functional/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 533946
+oscarazu@google.com
+keunyoung@google.com
diff --git a/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
index 362ab41..615fde0 100644
--- a/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
+++ b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
@@ -496,10 +496,26 @@
  *  - program changes exactly to what was requested.
  */
 TEST_P(BroadcastRadioHalTest, DabTune) {
+    Result halResult;
+    hidl_vec<DabTableEntry> config;
+    auto cb = [&](Result result, hidl_vec<DabTableEntry> configCb) {
+        halResult = result;
+        config = configCb;
+    };
+    auto hidlResult = mModule->getDabRegionConfig(cb);
+    ASSERT_TRUE(hidlResult.isOk());
+
+    if (halResult == Result::NOT_SUPPORTED) {
+        printSkipped("DAB not supported");
+        return;
+    }
+    ASSERT_EQ(Result::OK, halResult);
+    ASSERT_NE(config.size(), 0U);
+
     ASSERT_TRUE(openSession());
 
     ProgramSelector sel = {};
-    uint64_t freq = 178352;
+    uint64_t freq = config[config.size() / 2].frequency;
     sel.primaryId = make_identifier(IdentifierType::DAB_FREQUENCY,freq);
 
     std::this_thread::sleep_for(gTuneWorkaround);
diff --git a/broadcastradio/common/vts/utils/Android.bp b/broadcastradio/common/vts/utils/Android.bp
index e08813b..dd48db3 100644
--- a/broadcastradio/common/vts/utils/Android.bp
+++ b/broadcastradio/common/vts/utils/Android.bp
@@ -34,5 +34,4 @@
         "-Wextra",
         "-Werror",
     ],
-    group_static_libs: true,
 }
diff --git a/camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.cpp b/camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.cpp
index 4cff1b7..7c3b982 100644
--- a/camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.cpp
+++ b/camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.cpp
@@ -450,7 +450,9 @@
         const sp<ICameraProviderCallback>& callback) {
     Mutex::Autolock _l(mCbLock);
     mCallbacks = callback;
-
+    if (mCallbacks == nullptr) {
+        return Status::OK;
+    }
     // Add and report all presenting external cameras.
     for (auto const& statusPair : mCameraStatusMap) {
         int id = std::stoi(statusPair.first);
diff --git a/camera/provider/2.4/vts/functional/Android.bp b/camera/provider/2.4/vts/functional/Android.bp
index 8886ee1..d2f61a5 100644
--- a/camera/provider/2.4/vts/functional/Android.bp
+++ b/camera/provider/2.4/vts/functional/Android.bp
@@ -26,6 +26,7 @@
 cc_test {
     name: "VtsHalCameraProviderV2_4TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: ["VtsHalCameraProviderV2_4TargetTest.cpp"],
     srcs: ["VtsHalCameraProviderV2_4TargetTest.cpp"],
 
     // TODO(b/64437680): Assume these are always available on the device.
diff --git a/camera/provider/2.4/vts/functional/OWNERS b/camera/provider/2.4/vts/functional/OWNERS
new file mode 100644
index 0000000..479f465
--- /dev/null
+++ b/camera/provider/2.4/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 41727
+epeev@google.com
diff --git a/cas/1.0/default/android.hardware.cas@1.0-service-lazy.rc b/cas/1.0/default/android.hardware.cas@1.0-service-lazy.rc
index 443549a..622ee8f 100644
--- a/cas/1.0/default/android.hardware.cas@1.0-service-lazy.rc
+++ b/cas/1.0/default/android.hardware.cas@1.0-service-lazy.rc
@@ -6,4 +6,4 @@
     user media
     group mediadrm drmrpc
     ioprio rt 4
-    writepid /dev/cpuset/foreground/tasks
+    task_profiles ProcessCapacityHigh
diff --git a/cas/1.0/default/android.hardware.cas@1.0-service.rc b/cas/1.0/default/android.hardware.cas@1.0-service.rc
index 74f2f96..5df4825 100644
--- a/cas/1.0/default/android.hardware.cas@1.0-service.rc
+++ b/cas/1.0/default/android.hardware.cas@1.0-service.rc
@@ -3,4 +3,4 @@
     user media
     group mediadrm drmrpc
     ioprio rt 4
-    writepid /dev/cpuset/foreground/tasks
+    task_profiles ProcessCapacityHigh
diff --git a/cas/1.0/vts/functional/OWNERS b/cas/1.0/vts/functional/OWNERS
new file mode 100644
index 0000000..7d8c2ee
--- /dev/null
+++ b/cas/1.0/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 1344
+include ../../../1.2/vts/functional/OWNERS
diff --git a/cas/1.1/default/android.hardware.cas@1.1-service-lazy.rc b/cas/1.1/default/android.hardware.cas@1.1-service-lazy.rc
index 73c505d..0721dc3 100644
--- a/cas/1.1/default/android.hardware.cas@1.1-service-lazy.rc
+++ b/cas/1.1/default/android.hardware.cas@1.1-service-lazy.rc
@@ -7,4 +7,4 @@
     user media
     group mediadrm drmrpc
     ioprio rt 4
-    writepid /dev/cpuset/foreground/tasks
+    task_profiles ProcessCapacityHigh
diff --git a/cas/1.1/default/android.hardware.cas@1.1-service.rc b/cas/1.1/default/android.hardware.cas@1.1-service.rc
index 4081fe1..132d943 100644
--- a/cas/1.1/default/android.hardware.cas@1.1-service.rc
+++ b/cas/1.1/default/android.hardware.cas@1.1-service.rc
@@ -3,4 +3,4 @@
     user media
     group mediadrm drmrpc
     ioprio rt 4
-    writepid /dev/cpuset/foreground/tasks
+    task_profiles ProcessCapacityHigh
diff --git a/cas/1.1/vts/functional/OWNERS b/cas/1.1/vts/functional/OWNERS
index 29246ed..7d8c2ee 100644
--- a/cas/1.1/vts/functional/OWNERS
+++ b/cas/1.1/vts/functional/OWNERS
@@ -1,3 +1,2 @@
-nchalko@google.com
-chz@google.com
-quxiangfang@google.com
+# Bug component: 1344
+include ../../../1.2/vts/functional/OWNERS
diff --git a/cas/1.2/default/android.hardware.cas@1.2-service-lazy.rc b/cas/1.2/default/android.hardware.cas@1.2-service-lazy.rc
index 1c75100..d91fdce 100644
--- a/cas/1.2/default/android.hardware.cas@1.2-service-lazy.rc
+++ b/cas/1.2/default/android.hardware.cas@1.2-service-lazy.rc
@@ -8,4 +8,4 @@
     user media
     group mediadrm drmrpc
     ioprio rt 4
-    writepid /dev/cpuset/foreground/tasks
+    task_profiles ProcessCapacityHigh
diff --git a/cas/1.2/default/android.hardware.cas@1.2-service.rc b/cas/1.2/default/android.hardware.cas@1.2-service.rc
index d1c853e..b22971a 100644
--- a/cas/1.2/default/android.hardware.cas@1.2-service.rc
+++ b/cas/1.2/default/android.hardware.cas@1.2-service.rc
@@ -3,4 +3,4 @@
     user media
     group mediadrm drmrpc
     ioprio rt 4
-    writepid /dev/cpuset/foreground/tasks
+    task_profiles ProcessCapacityHigh
diff --git a/cas/1.2/vts/functional/OWNERS b/cas/1.2/vts/functional/OWNERS
index 29246ed..4c55752 100644
--- a/cas/1.2/vts/functional/OWNERS
+++ b/cas/1.2/vts/functional/OWNERS
@@ -1,3 +1,3 @@
-nchalko@google.com
-chz@google.com
+# Bug component: 1344
 quxiangfang@google.com
+hgchen@google.com
diff --git a/common/aidl/Android.bp b/common/aidl/Android.bp
index 028c923..549d970 100644
--- a/common/aidl/Android.bp
+++ b/common/aidl/Android.bp
@@ -30,6 +30,7 @@
         ndk: {
             apex_available: [
                 "//apex_available:platform",
+                "com.android.bluetooth",
                 "com.android.media.swcodec",
                 "com.android.neuralnetworks",
             ],
diff --git a/common/fmq/aidl/Android.bp b/common/fmq/aidl/Android.bp
index fb2f4e0..6fd4200 100644
--- a/common/fmq/aidl/Android.bp
+++ b/common/fmq/aidl/Android.bp
@@ -19,16 +19,23 @@
         "android/hardware/common/fmq/*.aidl",
     ],
     imports: [
-        "android.hardware.common",
+        "android.hardware.common-V2",
     ],
     stability: "vintf",
     backend: {
         java: {
-            enabled: false,
+            sdk_version: "module_current",
         },
         cpp: {
             enabled: false,
         },
+        ndk: {
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.bluetooth",
+            ],
+            min_sdk_version: "29",
+        },
     },
     versions: ["1"],
 }
diff --git a/common/fmq/aidl/aidl_api/android.hardware.common.fmq/1/.hash b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/1/.hash
index da122e6..b88c5fc 100644
--- a/common/fmq/aidl/aidl_api/android.hardware.common.fmq/1/.hash
+++ b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/1/.hash
@@ -1 +1,2 @@
 12cf0ce8614557cc0efe73bdf011f5193f7a8653
+6a780550f6e6965d6969fd7964c3ca81b6b0ccdf
diff --git a/common/fmq/aidl/aidl_api/android.hardware.common.fmq/1/android/hardware/common/fmq/GrantorDescriptor.aidl b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/1/android/hardware/common/fmq/GrantorDescriptor.aidl
index cf7048b..0430c6e 100644
--- a/common/fmq/aidl/aidl_api/android.hardware.common.fmq/1/android/hardware/common/fmq/GrantorDescriptor.aidl
+++ b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/1/android/hardware/common/fmq/GrantorDescriptor.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.common.fmq;
+/* @hide */
 @VintfStability
 parcelable GrantorDescriptor {
   int fdIndex;
diff --git a/common/fmq/aidl/aidl_api/android.hardware.common.fmq/1/android/hardware/common/fmq/MQDescriptor.aidl b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/1/android/hardware/common/fmq/MQDescriptor.aidl
index add4b64..ab3af0f 100644
--- a/common/fmq/aidl/aidl_api/android.hardware.common.fmq/1/android/hardware/common/fmq/MQDescriptor.aidl
+++ b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/1/android/hardware/common/fmq/MQDescriptor.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.common.fmq;
+/* @hide */
 @VintfStability
 parcelable MQDescriptor<T, Flavor> {
   android.hardware.common.fmq.GrantorDescriptor[] grantors;
diff --git a/common/fmq/aidl/aidl_api/android.hardware.common.fmq/1/android/hardware/common/fmq/SynchronizedReadWrite.aidl b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/1/android/hardware/common/fmq/SynchronizedReadWrite.aidl
index 12c61ba..72bab1c 100644
--- a/common/fmq/aidl/aidl_api/android.hardware.common.fmq/1/android/hardware/common/fmq/SynchronizedReadWrite.aidl
+++ b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/1/android/hardware/common/fmq/SynchronizedReadWrite.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.common.fmq;
+/* @hide */
 @VintfStability
 enum SynchronizedReadWrite {
   EMPTY = 0,
diff --git a/common/fmq/aidl/aidl_api/android.hardware.common.fmq/1/android/hardware/common/fmq/UnsynchronizedWrite.aidl b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/1/android/hardware/common/fmq/UnsynchronizedWrite.aidl
index f99528d..f308688 100644
--- a/common/fmq/aidl/aidl_api/android.hardware.common.fmq/1/android/hardware/common/fmq/UnsynchronizedWrite.aidl
+++ b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/1/android/hardware/common/fmq/UnsynchronizedWrite.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.common.fmq;
+/* @hide */
 @VintfStability
 enum UnsynchronizedWrite {
   EMPTY = 0,
diff --git a/common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/GrantorDescriptor.aidl b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/GrantorDescriptor.aidl
index cf7048b..0430c6e 100644
--- a/common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/GrantorDescriptor.aidl
+++ b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/GrantorDescriptor.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.common.fmq;
+/* @hide */
 @VintfStability
 parcelable GrantorDescriptor {
   int fdIndex;
diff --git a/common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/MQDescriptor.aidl b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/MQDescriptor.aidl
index add4b64..ab3af0f 100644
--- a/common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/MQDescriptor.aidl
+++ b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/MQDescriptor.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.common.fmq;
+/* @hide */
 @VintfStability
 parcelable MQDescriptor<T, Flavor> {
   android.hardware.common.fmq.GrantorDescriptor[] grantors;
diff --git a/common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/SynchronizedReadWrite.aidl b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/SynchronizedReadWrite.aidl
index 12c61ba..72bab1c 100644
--- a/common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/SynchronizedReadWrite.aidl
+++ b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/SynchronizedReadWrite.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.common.fmq;
+/* @hide */
 @VintfStability
 enum SynchronizedReadWrite {
   EMPTY = 0,
diff --git a/common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/UnsynchronizedWrite.aidl b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/UnsynchronizedWrite.aidl
index f99528d..f308688 100644
--- a/common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/UnsynchronizedWrite.aidl
+++ b/common/fmq/aidl/aidl_api/android.hardware.common.fmq/current/android/hardware/common/fmq/UnsynchronizedWrite.aidl
@@ -32,6 +32,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.common.fmq;
+/* @hide */
 @VintfStability
 enum UnsynchronizedWrite {
   EMPTY = 0,
diff --git a/common/fmq/aidl/android/hardware/common/fmq/GrantorDescriptor.aidl b/common/fmq/aidl/android/hardware/common/fmq/GrantorDescriptor.aidl
index 672415e..c6ca470 100644
--- a/common/fmq/aidl/android/hardware/common/fmq/GrantorDescriptor.aidl
+++ b/common/fmq/aidl/android/hardware/common/fmq/GrantorDescriptor.aidl
@@ -18,6 +18,7 @@
 
 /*
  * Included in MQDescriptor, for use with libfmq.
+ * @hide
  */
 @VintfStability
 parcelable GrantorDescriptor {
diff --git a/common/fmq/aidl/android/hardware/common/fmq/MQDescriptor.aidl b/common/fmq/aidl/android/hardware/common/fmq/MQDescriptor.aidl
index 46622f0..f2fcb31 100644
--- a/common/fmq/aidl/android/hardware/common/fmq/MQDescriptor.aidl
+++ b/common/fmq/aidl/android/hardware/common/fmq/MQDescriptor.aidl
@@ -26,6 +26,7 @@
  * T - is used to specify the type of the payload
  * Flavor - is used to specify the type of the queue using
  * android.hardware.common.SynchronizedReadWrite or UnsynchronizedWrite
+ * @hide
  */
 @VintfStability
 parcelable MQDescriptor<T, Flavor> {
diff --git a/common/fmq/aidl/android/hardware/common/fmq/SynchronizedReadWrite.aidl b/common/fmq/aidl/android/hardware/common/fmq/SynchronizedReadWrite.aidl
index 8c33442..8b1d0a1 100644
--- a/common/fmq/aidl/android/hardware/common/fmq/SynchronizedReadWrite.aidl
+++ b/common/fmq/aidl/android/hardware/common/fmq/SynchronizedReadWrite.aidl
@@ -20,6 +20,7 @@
  * For use with android.hardware.common.MQDescriptor to specify which type of
  * queue to use. SynchronizedReadWrite is single reader, single writer, with no
  * overflow. All messages written need to be read.
+ * @hide
  */
 @VintfStability
 enum SynchronizedReadWrite {
diff --git a/common/fmq/aidl/android/hardware/common/fmq/UnsynchronizedWrite.aidl b/common/fmq/aidl/android/hardware/common/fmq/UnsynchronizedWrite.aidl
index 24c4cce..5fe48c8 100644
--- a/common/fmq/aidl/android/hardware/common/fmq/UnsynchronizedWrite.aidl
+++ b/common/fmq/aidl/android/hardware/common/fmq/UnsynchronizedWrite.aidl
@@ -20,6 +20,7 @@
  * For use with android.hardware.common.MQDescriptor to specify which type of
  * queue to use. UnsynchronizedWrite is single writer, multiple reader, with
  * overflow. If messages are not read fast enough, they can be overwritten.
+ * @hide
  */
 @VintfStability
 enum UnsynchronizedWrite {
diff --git a/common/support/Android.bp b/common/support/Android.bp
index 730798d..718901e 100644
--- a/common/support/Android.bp
+++ b/common/support/Android.bp
@@ -11,11 +11,15 @@
     name: "libaidlcommonsupport",
     vendor_available: true,
     host_supported: true,
-    defaults: ["libbinder_ndk_host_user"],
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
     srcs: ["NativeHandle.cpp"],
     export_include_dirs: ["include"],
     shared_libs: [
-        "android.hardware.common-V2-ndk_platform",
+        "android.hardware.common-V2-ndk",
         "libcutils",
     ],
     apex_available: [
@@ -28,10 +32,14 @@
 cc_test {
     name: "libaidlcommonsupport_test",
     host_supported: true,
-    defaults: ["libbinder_ndk_host_user"],
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
     srcs: ["test.cpp"],
     static_libs: [
-        "android.hardware.common-V2-ndk_platform",
+        "android.hardware.common-V2-ndk",
         "libaidlcommonsupport",
     ],
     shared_libs: [
diff --git a/compatibility_matrices/Android.bp b/compatibility_matrices/Android.bp
index 31fa1ae..524242f 100644
--- a/compatibility_matrices/Android.bp
+++ b/compatibility_matrices/Android.bp
@@ -74,15 +74,25 @@
 }
 
 vintf_compatibility_matrix {
+    name: "framework_compatibility_matrix.7.xml",
+    stem: "compatibility_matrix.7.xml",
+    srcs: [
+        "compatibility_matrix.7.xml",
+    ],
+    kernel_configs: [
+        "kernel_config_t_5.10",
+        "kernel_config_t_5.15",
+    ],
+}
+
+vintf_compatibility_matrix {
     name: "framework_compatibility_matrix.current.xml",
-    enabled: false,
     stem: "compatibility_matrix.current.xml",
     srcs: [
         "compatibility_matrix.current.xml",
     ],
     kernel_configs: [
-        "kernel_config_current_4.19",
-        "kernel_config_current_5.4",
         "kernel_config_current_5.10",
+        "kernel_config_current_5.15",
     ],
 }
diff --git a/compatibility_matrices/Android.mk b/compatibility_matrices/Android.mk
index 4cefb55..d19f0da 100644
--- a/compatibility_matrices/Android.mk
+++ b/compatibility_matrices/Android.mk
@@ -102,6 +102,8 @@
     framework_compatibility_matrix.4.xml \
     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/build/vintf_compatibility_matrix.go b/compatibility_matrices/build/vintf_compatibility_matrix.go
index f1bd0ae..c72cbde 100644
--- a/compatibility_matrices/build/vintf_compatibility_matrix.go
+++ b/compatibility_matrices/build/vintf_compatibility_matrix.go
@@ -153,7 +153,7 @@
 		if k, ok := m.(*configs.KernelConfigRule); ok {
 			inputPaths = append(inputPaths, k.OutputPath())
 		} else {
-			ctx.PropertyErrorf("kernel_config",
+			ctx.PropertyErrorf("kernel_configs",
 				"module %q is not a kernel_config", ctx.OtherModuleName(m))
 		}
 	})
diff --git a/compatibility_matrices/compatibility_matrix.3.xml b/compatibility_matrices/compatibility_matrix.3.xml
index a75ed25..468735d 100644
--- a/compatibility_matrices/compatibility_matrix.3.xml
+++ b/compatibility_matrices/compatibility_matrix.3.xml
@@ -207,7 +207,10 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="false">
+    <!-- Either the AIDL or the HIDL health HAL must exist on the device.
+         If the HIDL health HAL exists, it must be at least version 2.0.
+         See DeviceManifestTest.HealthHal -->
+    <hal format="hidl" optional="true">
         <name>android.hardware.health</name>
         <version>2.0</version>
         <interface>
diff --git a/compatibility_matrices/compatibility_matrix.4.xml b/compatibility_matrices/compatibility_matrix.4.xml
index 3b8ee21..96f291f 100644
--- a/compatibility_matrices/compatibility_matrix.4.xml
+++ b/compatibility_matrices/compatibility_matrix.4.xml
@@ -213,7 +213,10 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="false">
+    <!-- Either the AIDL or the HIDL health HAL must exist on the device.
+         If the HIDL health HAL exists, it must be at least version 2.0.
+         See DeviceManifestTest.HealthHal -->
+    <hal format="hidl" optional="true">
         <name>android.hardware.health</name>
         <version>2.0</version>
         <interface>
diff --git a/compatibility_matrices/compatibility_matrix.5.xml b/compatibility_matrices/compatibility_matrix.5.xml
index 0fb21a7..3642814 100644
--- a/compatibility_matrices/compatibility_matrix.5.xml
+++ b/compatibility_matrices/compatibility_matrix.5.xml
@@ -238,7 +238,10 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="false">
+    <!-- Either the AIDL or the HIDL health HAL must exist on the device.
+         If the HIDL health HAL exists, it must be at least version 2.1.
+         See DeviceManifestTest.HealthHal -->
+    <hal format="hidl" optional="true">
         <name>android.hardware.health</name>
         <version>2.1</version>
         <interface>
diff --git a/compatibility_matrices/compatibility_matrix.6.xml b/compatibility_matrices/compatibility_matrix.6.xml
index aee2c51..9c42cb0 100644
--- a/compatibility_matrices/compatibility_matrix.6.xml
+++ b/compatibility_matrices/compatibility_matrix.6.xml
@@ -268,7 +268,10 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="false">
+    <!-- Either the AIDL or the HIDL health HAL must exist on the device.
+         If the HIDL health HAL exists, it must be at least version 2.1.
+         See DeviceManifestTest.HealthHal -->
+    <hal format="hidl" optional="true">
         <name>android.hardware.health</name>
         <version>2.1</version>
         <interface>
diff --git a/compatibility_matrices/compatibility_matrix.7.xml b/compatibility_matrices/compatibility_matrix.7.xml
new file mode 100644
index 0000000..6967671
--- /dev/null
+++ b/compatibility_matrices/compatibility_matrix.7.xml
@@ -0,0 +1,720 @@
+<compatibility-matrix version="1.0" type="framework" level="7">
+    <hal format="hidl" optional="true">
+        <name>android.hardware.atrace</name>
+        <version>1.0</version>
+        <interface>
+            <name>IAtraceDevice</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.audio</name>
+        <version>6.0</version>
+        <version>7.0-1</version>
+        <interface>
+            <name>IDevicesFactory</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.audio.effect</name>
+        <version>6.0</version>
+        <version>7.0</version>
+        <interface>
+            <name>IEffectsFactory</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+         <name>android.hardware.authsecret</name>
+         <version>1</version>
+         <interface>
+             <name>IAuthSecret</name>
+             <instance>default</instance>
+         </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.authsecret</name>
+        <version>1.0</version>
+        <interface>
+            <name>IAuthSecret</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.automotive.audiocontrol</name>
+        <interface>
+            <name>IAudioControl</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.automotive.can</name>
+        <version>1.0</version>
+        <interface>
+            <name>ICanBus</name>
+            <regex-instance>.*</regex-instance>
+        </interface>
+        <interface>
+            <name>ICanController</name>
+            <regex-instance>.*</regex-instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.automotive.evs</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>IEvsEnumerator</name>
+            <instance>default</instance>
+            <regex-instance>[a-z]+/[0-9]+</regex-instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.automotive.occupant_awareness</name>
+        <version>1</version>
+        <interface>
+            <name>IOccupantAwareness</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.automotive.sv</name>
+        <version>1.0</version>
+        <interface>
+            <name>ISurroundViewService</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.automotive.vehicle</name>
+        <version>2.0</version>
+        <interface>
+            <name>IVehicle</name>
+            <instance>default</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>
+        <interface>
+            <name>IFace</name>
+            <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>
+        <interface>
+            <name>IFingerprint</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.bluetooth</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>IBluetoothHci</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.bluetooth.audio</name>
+        <interface>
+            <name>IBluetoothAudioProviderFactory</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.boot</name>
+        <version>1.2</version>
+        <interface>
+            <name>IBootControl</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.broadcastradio</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>IBroadcastRadioFactory</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.broadcastradio</name>
+        <version>2.0</version>
+        <interface>
+            <name>IBroadcastRadio</name>
+            <regex-instance>.*</regex-instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.camera.provider</name>
+        <version>2.4-7</version>
+        <interface>
+            <name>ICameraProvider</name>
+            <regex-instance>[^/]+/[0-9]+</regex-instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.cas</name>
+        <version>1.1-2</version>
+        <interface>
+            <name>IMediaCasService</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.confirmationui</name>
+        <version>1.0</version>
+        <interface>
+            <name>IConfirmationUI</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.contexthub</name>
+        <version>1.2</version>
+        <interface>
+            <name>IContexthub</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.drm</name>
+        <version>1.3-4</version>
+        <interface>
+            <name>ICryptoFactory</name>
+            <regex-instance>.*</regex-instance>
+        </interface>
+        <interface>
+            <name>IDrmFactory</name>
+            <regex-instance>.*</regex-instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.dumpstate</name>
+        <interface>
+            <name>IDumpstateDevice</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.gatekeeper</name>
+        <version>1.0</version>
+        <interface>
+            <name>IGatekeeper</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.gnss</name>
+        <version>2.0-1</version>
+        <interface>
+            <name>IGnss</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.gnss</name>
+        <interface>
+            <name>IGnss</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.graphics.allocator</name>
+        <!-- New, non-Go devices should use 4.0, tested in vts_treble_vintf_vendor_test -->
+        <version>2.0</version>
+        <version>3.0</version>
+        <version>4.0</version>
+        <interface>
+            <name>IAllocator</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.graphics.composer</name>
+        <version>2.1-4</version>
+        <interface>
+            <name>IComposer</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.graphics.mapper</name>
+        <!-- New, non-Go devices should use 4.0, tested in vts_treble_vintf_vendor_test -->
+        <version>2.1</version>
+        <version>3.0</version>
+        <version>4.0</version>
+        <interface>
+            <name>IMapper</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="false">
+        <name>android.hardware.health</name>
+        <version>1</version>
+        <interface>
+            <name>IHealth</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.health.storage</name>
+        <version>1</version>
+        <interface>
+            <name>IStorage</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.identity</name>
+        <version>1-4</version>
+        <interface>
+            <name>IIdentityCredentialStore</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.oemlock</name>
+        <version>1</version>
+        <interface>
+            <name>IOemLock</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.ir</name>
+        <version>1</version>
+        <interface>
+            <name>IConsumerIr</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.input.classifier</name>
+        <version>1.0</version>
+        <interface>
+            <name>IInputClassifier</name>
+            <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>
+        <interface>
+            <name>IDiceDevice</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.security.keymint</name>
+        <version>1-2</version>
+        <interface>
+            <name>IKeyMintDevice</name>
+            <instance>default</instance>
+            <instance>strongbox</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.security.keymint</name>
+        <version>1-2</version>
+        <interface>
+            <name>IRemotelyProvisionedComponent</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.light</name>
+        <version>1</version>
+        <interface>
+            <name>ILights</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.media.c2</name>
+        <version>1.0-2</version>
+        <interface>
+            <name>IComponentStore</name>
+            <regex-instance>default[0-9]*</regex-instance>
+            <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>
+        <interface>
+            <name>IMemtrack</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.neuralnetworks</name>
+        <version>1.0-3</version>
+        <interface>
+            <name>IDevice</name>
+            <regex-instance>.*</regex-instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.neuralnetworks</name>
+        <version>1-4</version>
+        <interface>
+            <name>IDevice</name>
+            <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>
+            <name>INfc</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.oemlock</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOemLock</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="false">
+        <name>android.hardware.power</name>
+        <version>1-2</version>
+        <interface>
+            <name>IPower</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.power.stats</name>
+        <interface>
+            <name>IPowerStats</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.radio.config</name>
+        <version>1</version>
+        <interface>
+            <name>IRadioConfig</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.radio.data</name>
+        <version>1</version>
+        <interface>
+            <name>IRadioData</name>
+            <instance>slot1</instance>
+            <instance>slot2</instance>
+            <instance>slot3</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.radio.messaging</name>
+        <version>1</version>
+        <interface>
+            <name>IRadioMessaging</name>
+            <instance>slot1</instance>
+            <instance>slot2</instance>
+            <instance>slot3</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.radio.modem</name>
+        <version>1</version>
+        <interface>
+            <name>IRadioModem</name>
+            <instance>slot1</instance>
+            <instance>slot2</instance>
+            <instance>slot3</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.radio.network</name>
+        <version>1</version>
+        <interface>
+            <name>IRadioNetwork</name>
+            <instance>slot1</instance>
+            <instance>slot2</instance>
+            <instance>slot3</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.radio.sim</name>
+        <version>1</version>
+        <interface>
+            <name>IRadioSim</name>
+            <instance>slot1</instance>
+            <instance>slot2</instance>
+            <instance>slot3</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.radio.voice</name>
+        <version>1</version>
+        <interface>
+            <name>IRadioVoice</name>
+            <instance>slot1</instance>
+            <instance>slot2</instance>
+            <instance>slot3</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.radio</name>
+        <version>1.2</version>
+        <interface>
+            <name>ISap</name>
+            <instance>slot1</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.renderscript</name>
+        <version>1.0</version>
+        <interface>
+            <name>IDevice</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.rebootescrow</name>
+        <version>1</version>
+        <interface>
+            <name>IRebootEscrow</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.secure_element</name>
+        <version>1.0-2</version>
+        <interface>
+            <name>ISecureElement</name>
+            <regex-instance>eSE[1-9][0-9]*</regex-instance>
+            <regex-instance>SIM[1-9][0-9]*</regex-instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.security.secureclock</name>
+        <version>1</version>
+        <interface>
+            <name>ISecureClock</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.security.sharedsecret</name>
+        <version>1</version>
+        <interface>
+            <name>ISharedSecret</name>
+            <instance>default</instance>
+            <instance>strongbox</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.sensors</name>
+        <version>1.0</version>
+        <version>2.0-1</version>
+        <interface>
+            <name>ISensors</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.soundtrigger</name>
+        <version>2.3</version>
+        <interface>
+            <name>ISoundTriggerHw</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tetheroffload.config</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOffloadConfig</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tetheroffload.control</name>
+        <version>1.1</version>
+        <interface>
+            <name>IOffloadControl</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.thermal</name>
+        <version>2.0</version>
+        <interface>
+            <name>IThermal</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tv.cec</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>IHdmiCec</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tv.input</name>
+        <version>1.0</version>
+        <interface>
+            <name>ITvInput</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tv.tuner</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>ITuner</name>
+            <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="hidl" optional="true">
+        <name>android.hardware.usb.gadget</name>
+        <version>1.0-2</version>
+        <interface>
+            <name>IUsbGadget</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.vibrator</name>
+        <version>1-2</version>
+        <interface>
+            <name>IVibrator</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.vibrator</name>
+        <version>1-2</version>
+        <interface>
+            <name>IVibratorManager</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.weaver</name>
+        <version>1.0</version>
+        <interface>
+            <name>IWeaver</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.weaver</name>
+        <version>1</version>
+        <interface>
+            <name>IWeaver</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.wifi</name>
+        <version>1.3-5</version>
+        <interface>
+            <name>IWifi</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.wifi.hostapd</name>
+        <version>1.0-3</version>
+        <interface>
+            <name>IHostapd</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.wifi.hostapd</name>
+        <version>1</version>
+        <interface>
+            <name>IHostapd</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.wifi.supplicant</name>
+        <version>1.2-4</version>
+        <interface>
+            <name>ISupplicant</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.wifi.supplicant</name>
+        <interface>
+            <name>ISupplicant</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</compatibility-matrix>
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index eb6ead3..e006091 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -1,4 +1,4 @@
-<compatibility-matrix version="1.0" type="framework" level="7">
+<compatibility-matrix version="1.0" type="framework" level="8">
     <hal format="hidl" optional="true">
         <name>android.hardware.atrace</name>
         <version>1.0</version>
@@ -10,7 +10,7 @@
     <hal format="hidl" optional="false">
         <name>android.hardware.audio</name>
         <version>6.0</version>
-        <version>7.0</version>
+        <version>7.0-1</version>
         <interface>
             <name>IDevicesFactory</name>
             <instance>default</instance>
@@ -131,11 +131,10 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="true">
+    <hal format="aidl" optional="true">
         <name>android.hardware.bluetooth.audio</name>
-        <version>2.0-1</version>
         <interface>
-            <name>IBluetoothAudioProvidersFactory</name>
+            <name>IBluetoothAudioProviderFactory</name>
             <instance>default</instance>
         </interface>
     </hal>
@@ -147,6 +146,13 @@
             <instance>default</instance>
         </interface>
     </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.boot</name>
+        <interface>
+            <name>IBootControl</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.broadcastradio</name>
         <version>1.0-1</version>
@@ -207,9 +213,8 @@
             <regex-instance>.*</regex-instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="true">
+    <hal format="aidl" optional="true">
         <name>android.hardware.dumpstate</name>
-        <version>1.1</version>
         <interface>
             <name>IDumpstateDevice</name>
             <instance>default</instance>
@@ -268,9 +273,9 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="false">
+    <hal format="aidl" optional="false">
         <name>android.hardware.health</name>
-        <version>2.1</version>
+        <version>1</version>
         <interface>
             <name>IHealth</name>
             <instance>default</instance>
@@ -286,7 +291,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.identity</name>
-        <version>1-3</version>
+        <version>1-4</version>
         <interface>
             <name>IIdentityCredentialStore</name>
             <instance>default</instance>
@@ -300,9 +305,9 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="true">
+    <hal format="aidl" optional="true">
         <name>android.hardware.ir</name>
-        <version>1.0</version>
+        <version>1</version>
         <interface>
             <name>IConsumerIr</name>
             <instance>default</instance>
@@ -334,9 +339,17 @@
         </interface>
     </hal>
     <hal format="aidl" optional="true">
-        <name>android.hardware.security.keymint</name>
+        <name>android.hardware.security.dice</name>
         <version>1</version>
         <interface>
+            <name>IDiceDevice</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.security.keymint</name>
+        <version>1-2</version>
+        <interface>
             <name>IKeyMintDevice</name>
             <instance>default</instance>
             <instance>strongbox</instance>
@@ -344,6 +357,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.security.keymint</name>
+        <version>1-2</version>
         <interface>
             <name>IRemotelyProvisionedComponent</name>
             <instance>default</instance>
@@ -396,7 +410,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.neuralnetworks</name>
-        <version>1-2</version>
+        <version>1-4</version>
         <interface>
             <name>IDevice</name>
             <regex-instance>.*</regex-instance>
@@ -410,6 +424,13 @@
             <instance>default</instance>
         </interface>
     </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.nfc</name>
+        <interface>
+            <name>INfc</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.oemlock</name>
         <version>1.0</version>
@@ -433,11 +454,69 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="true">
-        <name>android.hardware.radio</name>
-        <version>1.6</version>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.radio.config</name>
+        <version>1</version>
         <interface>
-            <name>IRadio</name>
+            <name>IRadioConfig</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.radio.data</name>
+        <version>1</version>
+        <interface>
+            <name>IRadioData</name>
+            <instance>slot1</instance>
+            <instance>slot2</instance>
+            <instance>slot3</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.radio.messaging</name>
+        <version>1</version>
+        <interface>
+            <name>IRadioMessaging</name>
+            <instance>slot1</instance>
+            <instance>slot2</instance>
+            <instance>slot3</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.radio.modem</name>
+        <version>1</version>
+        <interface>
+            <name>IRadioModem</name>
+            <instance>slot1</instance>
+            <instance>slot2</instance>
+            <instance>slot3</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.radio.network</name>
+        <version>1</version>
+        <interface>
+            <name>IRadioNetwork</name>
+            <instance>slot1</instance>
+            <instance>slot2</instance>
+            <instance>slot3</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.radio.sim</name>
+        <version>1</version>
+        <interface>
+            <name>IRadioSim</name>
+            <instance>slot1</instance>
+            <instance>slot2</instance>
+            <instance>slot3</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.radio.voice</name>
+        <version>1</version>
+        <interface>
+            <name>IRadioVoice</name>
             <instance>slot1</instance>
             <instance>slot2</instance>
             <instance>slot3</instance>
@@ -452,25 +531,6 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
-        <name>android.hardware.radio.config</name>
-        <!--
-        See compatibility_matrix.4.xml on versioning of radio config HAL.
-        -->
-        <version>1.1</version>
-        <interface>
-            <name>IRadioConfig</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl" optional="true">
-        <name>android.hardware.radio.config</name>
-        <version>1.3</version>
-        <interface>
-            <name>IRadioConfig</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl" optional="true">
         <name>android.hardware.renderscript</name>
         <version>1.0</version>
         <interface>
@@ -545,7 +605,7 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="true">
+    <hal format="hidl" optional="false">
         <name>android.hardware.thermal</name>
         <version>2.0</version>
         <interface>
@@ -585,6 +645,13 @@
             <instance>default</instance>
         </interface>
     </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.usb</name>
+        <interface>
+            <name>IUsb</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.usb.gadget</name>
         <version>1.0-2</version>
@@ -641,6 +708,14 @@
             <instance>default</instance>
         </interface>
     </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.wifi.hostapd</name>
+        <version>1</version>
+        <interface>
+            <name>IHostapd</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.wifi.supplicant</name>
         <version>1.2-4</version>
@@ -649,4 +724,11 @@
             <instance>default</instance>
         </interface>
     </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.wifi.supplicant</name>
+        <interface>
+            <name>ISupplicant</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
 </compatibility-matrix>
diff --git a/compatibility_matrices/exclude/fcm_exclude.cpp b/compatibility_matrices/exclude/fcm_exclude.cpp
index e67c892..f34009d 100644
--- a/compatibility_matrices/exclude/fcm_exclude.cpp
+++ b/compatibility_matrices/exclude/fcm_exclude.cpp
@@ -51,11 +51,13 @@
             "android.hardware.media.bufferpool@2.0",
             "android.hardware.radio.config@1.2",
             // AIDL
+            "android.hardware.audio.common",
             "android.hardware.biometrics.common",
             "android.hardware.common",
             "android.hardware.common.fmq",
             "android.hardware.graphics.common",
             "android.hardware.keymaster",
+            "android.hardware.radio",
 
             // Fastboot HAL is only used by recovery. Recovery is owned by OEM. Framework
             // does not depend on this HAL, hence it is not declared in any manifests or matrices.
diff --git a/configstore/1.0/vts/functional/OWNERS b/configstore/1.0/vts/functional/OWNERS
new file mode 100644
index 0000000..edfa1b0
--- /dev/null
+++ b/configstore/1.0/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 24939
+lpy@google.com
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/contexthub/1.0/vts/functional/OWNERS b/contexthub/1.0/vts/functional/OWNERS
index 1a33a9e..f254cd5 100644
--- a/contexthub/1.0/vts/functional/OWNERS
+++ b/contexthub/1.0/vts/functional/OWNERS
@@ -1,7 +1,5 @@
+# Bug component: 156070
 #Context Hub team
 arthuri@google.com
 bduddie@google.com
 stange@google.com
-
-#VTS team
-dshi@google.com
diff --git a/contexthub/1.1/vts/functional/OWNERS b/contexthub/1.1/vts/functional/OWNERS
index 1a33a9e..2cf5bca 100644
--- a/contexthub/1.1/vts/functional/OWNERS
+++ b/contexthub/1.1/vts/functional/OWNERS
@@ -1,7 +1,2 @@
-#Context Hub team
-arthuri@google.com
-bduddie@google.com
-stange@google.com
-
-#VTS team
-dshi@google.com
+# Bug component: 156070
+include ../../../1.0/vts/functional/OWNERS
diff --git a/contexthub/1.2/vts/functional/OWNERS b/contexthub/1.2/vts/functional/OWNERS
index 1a33a9e..2cf5bca 100644
--- a/contexthub/1.2/vts/functional/OWNERS
+++ b/contexthub/1.2/vts/functional/OWNERS
@@ -1,7 +1,2 @@
-#Context Hub team
-arthuri@google.com
-bduddie@google.com
-stange@google.com
-
-#VTS team
-dshi@google.com
+# Bug component: 156070
+include ../../../1.0/vts/functional/OWNERS
diff --git a/current.txt b/current.txt
index 2373c39..6a77e19 100644
--- a/current.txt
+++ b/current.txt
@@ -904,4 +904,10 @@
 # HALs released in Android SCv2
 77f6fcf3fd0dd3e424d8a0292094ebd17e4c35454bb9abbd3a6cbed1aba70765 android.hardware.camera.metadata@3.7::types
 
+# ABI preserving changes to HALs during Android T
+62ace52d9c3ff1f60f94118557a2aaf0b953513e59dcd34d5f94ae28d4c7e780 android.hardware.fastboot@1.0::IFastboot
+d0fb32f3ddeb9af7115ab32905225ea69b930d2472be8e9610f0cf136c15aefb android.hardware.keymaster@4.0::IKeymasterDevice # b/210424594
+ca62a2a95d173ed323309e5e00f653ad3cceec82a6e5e4976a249cb5aafe2515 android.hardware.neuralnetworks@1.2::types
+fa76bced6b1b71c40fc706c508a9011284c57f57831cd0cf5f45653ed4ea463e android.hardware.neuralnetworks@1.3::types
+
 # There should be no more HIDL HALs - please use AIDL instead.
diff --git a/drm/1.0/default/android.hardware.drm@1.0-service-lazy.rc b/drm/1.0/default/android.hardware.drm@1.0-service-lazy.rc
index 4b32f7f..e5ae5cd 100644
--- a/drm/1.0/default/android.hardware.drm@1.0-service-lazy.rc
+++ b/drm/1.0/default/android.hardware.drm@1.0-service-lazy.rc
@@ -7,4 +7,4 @@
     user media
     group mediadrm drmrpc
     ioprio rt 4
-    writepid /dev/cpuset/foreground/tasks
+    task_profiles ProcessCapacityHigh
diff --git a/drm/1.0/default/android.hardware.drm@1.0-service.rc b/drm/1.0/default/android.hardware.drm@1.0-service.rc
index 790eded..2aba187 100644
--- a/drm/1.0/default/android.hardware.drm@1.0-service.rc
+++ b/drm/1.0/default/android.hardware.drm@1.0-service.rc
@@ -5,4 +5,4 @@
     user media
     group mediadrm drmrpc
     ioprio rt 4
-    writepid /dev/cpuset/foreground/tasks
+    task_profiles ProcessCapacityHigh
diff --git a/drm/1.0/vts/functional/Android.bp b/drm/1.0/vts/functional/Android.bp
index 5ea6ad3..8ca6a65 100644
--- a/drm/1.0/vts/functional/Android.bp
+++ b/drm/1.0/vts/functional/Android.bp
@@ -44,6 +44,10 @@
     local_include_dirs: [
         "include",
     ],
+    tidy_timeout_srcs: [
+        "drm_hal_clearkey_test.cpp",
+        "drm_hal_vendor_test.cpp",
+    ],
     srcs: [
         "drm_hal_clearkey_test.cpp",
         "drm_hal_vendor_test.cpp",
diff --git a/drm/1.0/vts/functional/OWNERS b/drm/1.0/vts/functional/OWNERS
new file mode 100644
index 0000000..0b13790
--- /dev/null
+++ b/drm/1.0/vts/functional/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 49079
+jtinker@google.com
+robertshih@google.com
+edwinwong@google.com
\ No newline at end of file
diff --git a/drm/1.1/vts/functional/Android.bp b/drm/1.1/vts/functional/Android.bp
index 656ec50..760b67e 100644
--- a/drm/1.1/vts/functional/Android.bp
+++ b/drm/1.1/vts/functional/Android.bp
@@ -32,6 +32,9 @@
     local_include_dirs: [
         "include",
     ],
+    tidy_timeout_srcs: [
+        "drm_hal_clearkey_test.cpp",
+    ],
     srcs: [
         "drm_hal_clearkey_test.cpp",
     ],
diff --git a/drm/1.1/vts/functional/OWNERS b/drm/1.1/vts/functional/OWNERS
new file mode 100644
index 0000000..0b13790
--- /dev/null
+++ b/drm/1.1/vts/functional/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 49079
+jtinker@google.com
+robertshih@google.com
+edwinwong@google.com
\ No newline at end of file
diff --git a/drm/1.2/vts/functional/Android.bp b/drm/1.2/vts/functional/Android.bp
index ca90ee9..dd22ebe 100644
--- a/drm/1.2/vts/functional/Android.bp
+++ b/drm/1.2/vts/functional/Android.bp
@@ -29,6 +29,9 @@
     local_include_dirs: [
         "include",
     ],
+    tidy_timeout_srcs: [
+        "drm_hal_test.cpp",
+    ],
     srcs: [
         "drm_hal_clearkey_module.cpp",
         "drm_hal_common.cpp",
diff --git a/drm/1.2/vts/functional/OWNERS b/drm/1.2/vts/functional/OWNERS
new file mode 100644
index 0000000..0b13790
--- /dev/null
+++ b/drm/1.2/vts/functional/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 49079
+jtinker@google.com
+robertshih@google.com
+edwinwong@google.com
\ No newline at end of file
diff --git a/drm/aidl/OWNERS b/drm/aidl/OWNERS
new file mode 100644
index 0000000..fa8fd20
--- /dev/null
+++ b/drm/aidl/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 49079
+edwinwong@google.com
+kelzhan@google.com
+robertshih@google.com
diff --git a/dumpstate/aidl/Android.bp b/dumpstate/aidl/Android.bp
new file mode 100644
index 0000000..22d836b
--- /dev/null
+++ b/dumpstate/aidl/Android.bp
@@ -0,0 +1,42 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//       http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+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.dumpstate",
+    vendor_available: true,
+    srcs: ["android/hardware/dumpstate/*.aidl"],
+    stability: "vintf",
+    backend: {
+        cpp: {
+            enabled: false,
+        },
+        java: {
+            enabled: false,
+        },
+        ndk: {
+            vndk: {
+                enabled: true,
+            },
+        },
+    },
+}
diff --git a/dumpstate/aidl/aidl_api/android.hardware.dumpstate/current/android/hardware/dumpstate/IDumpstateDevice.aidl b/dumpstate/aidl/aidl_api/android.hardware.dumpstate/current/android/hardware/dumpstate/IDumpstateDevice.aidl
new file mode 100644
index 0000000..4d78a4c
--- /dev/null
+++ b/dumpstate/aidl/aidl_api/android.hardware.dumpstate/current/android/hardware/dumpstate/IDumpstateDevice.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.dumpstate;
+@VintfStability
+interface IDumpstateDevice {
+  void dumpstateBoard(in ParcelFileDescriptor[] fd, in android.hardware.dumpstate.IDumpstateDevice.DumpstateMode mode, in long timeoutMillis);
+  boolean getVerboseLoggingEnabled();
+  void setVerboseLoggingEnabled(in boolean enable);
+  const int ERROR_UNSUPPORTED_MODE = 1;
+  const int ERROR_DEVICE_LOGGING_NOT_ENABLED = 2;
+  @Backing(type="int") @VintfStability
+  enum DumpstateMode {
+    FULL = 0,
+    INTERACTIVE = 1,
+    REMOTE = 2,
+    WEAR = 3,
+    CONNECTIVITY = 4,
+    WIFI = 5,
+    DEFAULT = 6,
+    PROTO = 7,
+  }
+}
diff --git a/dumpstate/aidl/android/hardware/dumpstate/IDumpstateDevice.aidl b/dumpstate/aidl/android/hardware/dumpstate/IDumpstateDevice.aidl
new file mode 100644
index 0000000..b994d04
--- /dev/null
+++ b/dumpstate/aidl/android/hardware/dumpstate/IDumpstateDevice.aidl
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.dumpstate;
+
+import android.os.ParcelFileDescriptor;
+
+@VintfStability
+interface IDumpstateDevice {
+    /**
+     * Constants that define the type of bug report being taken to restrict content appropriately.
+     */
+    @VintfStability
+    @Backing(type="int")
+    enum DumpstateMode {
+        /**
+         * Takes a bug report without user interference.
+         */
+        FULL = 0,
+        /**
+         * Interactive bug report, i.e. triggered by the user.
+         */
+        INTERACTIVE = 1,
+        /**
+         * Remote bug report triggered by DevicePolicyManager, for example.
+         */
+        REMOTE = 2,
+        /**
+         * Bug report triggered on a wear device.
+         */
+        WEAR = 3,
+        /**
+         * Bug report limited to only connectivity info (cellular, wifi, and networking). Sometimes
+         * called "telephony" in legacy contexts.
+         *
+         * All reported information MUST directly relate to connectivity debugging or customer
+         * support and MUST NOT contain unrelated private information. This information MUST NOT
+         * identify user-installed packages (UIDs are OK, package names are not), and MUST NOT
+         * contain logs of user application traffic.
+         */
+        CONNECTIVITY = 4,
+        /**
+         * Bug report limited to only wifi info.
+         */
+        WIFI = 5,
+        /**
+         * Default mode, This mode MUST be supported if the
+         * dumpstate HAL is implemented.
+         */
+        DEFAULT = 6,
+        /**
+         * Takes a report in protobuf.
+         *
+         * The content, if implemented, must be a binary protobuf message written to the first file
+         * descriptor of the native handle. The protobuf schema shall be defined by the vendor.
+         */
+        PROTO = 7,
+    }
+
+    /**
+     * Returned for cases where the device doesn't support the given DumpstateMode (e.g. a phone
+     * trying to use DumpstateMode::WEAR).
+     */
+    const int ERROR_UNSUPPORTED_MODE = 1;
+    /**
+     * Returned when device logging is not enabled.
+     */
+    const int ERROR_DEVICE_LOGGING_NOT_ENABLED = 2;
+
+    /**
+     * Dump device-specific state into the given file descriptors.
+     *
+     * One file descriptor must be passed to this method but two may be passed:
+     * the first descriptor must be used to dump device-specific state in text
+     * format, the second descriptor is optional and may be used to dump
+     * device-specific state in binary format.
+     *
+     * DumpstateMode can be used to limit the information that is output.
+     * For an example of when this is relevant, consider a bug report being generated with
+     * DumpstateMode::CONNECTIVITY - there is no reason to include camera or USB logs in this type
+     * of report.
+     *
+     * When verbose logging is disabled, getVerboseLoggingEnabled returns false, and this
+     * API is called, it may still output essential information but must not include
+     * information that identifies the user.
+     *
+     * @param fd array of file descriptors, with one or two valid file descriptors. The first FD is
+     *         for text output, the second (if present) is for binary output.
+     * @param mode A mode value to restrict dumped content.
+     * @param timeoutMillis An approximate "budget" for how much time this call has been allotted.
+     *     If execution runs longer than this, the IDumpstateDevice service may be killed and only
+     *     partial information will be included in the report.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |ERROR_UNSUPPORTED_MODE|,
+     *         |ERROR_DEVICE_LOGGING_NOT_ENABLED|
+     */
+    void dumpstateBoard(in ParcelFileDescriptor[] fd, in DumpstateMode mode, in long timeoutMillis);
+
+    /**
+     * Queries the current state of verbose device logging. Primarily for UI and informative
+     * purposes.
+     *
+     * Even if verbose logging has been disabled, dumpstateBoard may still be called by the
+     * dumpstate routine, and essential information that does not identify the user may be included.
+     *
+     * @return Whether or not verbose vendor logging is currently enabled.
+     */
+    boolean getVerboseLoggingEnabled();
+
+    /**
+     * Turns verbose device vendor logging on or off.
+     *
+     * The setting should be persistent across reboots. Underlying implementations may need to start
+     * vendor logging daemons, set system properties, or change logging masks, for example. Given
+     * that many vendor logs contain significant amounts of private information and may come with
+     * memory/storage/battery impacts, calling this method on a user build should only be done after
+     * user consent has been obtained, e.g. from a toggle in developer settings.
+     *
+     * Even if verbose logging has been disabled, dumpstateBoard may still be called by the
+     * dumpstate routine, and essential information that does not identify the user may be included.
+     *
+     * @param enable Whether to enable or disable verbose vendor logging.
+     */
+    void setVerboseLoggingEnabled(in boolean enable);
+}
diff --git a/dumpstate/aidl/default/Android.bp b/dumpstate/aidl/default/Android.bp
new file mode 100644
index 0000000..45fdc17
--- /dev/null
+++ b/dumpstate/aidl/default/Android.bp
@@ -0,0 +1,46 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//       http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+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.dumpstate-service.example",
+    relative_install_path: "hw",
+    init_rc: ["dumpstate-default.rc"],
+    vintf_fragments: ["dumpstate-default.xml"],
+    vendor: true,
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "libcutils",
+        "libdumpstateutil",
+        "liblog",
+        "libutils",
+        "android.hardware.dumpstate-V1-ndk",
+    ],
+    srcs: [
+        "main.cpp",
+        "Dumpstate.cpp",
+    ],
+    cflags: [
+        "-DLOG_TAG=\"android.hardware.dumpstate-service.example\"",
+    ],
+}
diff --git a/dumpstate/aidl/default/Dumpstate.cpp b/dumpstate/aidl/default/Dumpstate.cpp
new file mode 100644
index 0000000..a0730fb
--- /dev/null
+++ b/dumpstate/aidl/default/Dumpstate.cpp
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/properties.h>
+#include <log/log.h>
+#include "DumpstateUtil.h"
+
+#include "Dumpstate.h"
+
+using android::os::dumpstate::DumpFileToFd;
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace dumpstate {
+
+const char kVerboseLoggingProperty[] = "persist.dumpstate.verbose_logging.enabled";
+
+ndk::ScopedAStatus Dumpstate::dumpstateBoard(const std::vector<::ndk::ScopedFileDescriptor>& in_fds,
+                                             IDumpstateDevice::DumpstateMode in_mode,
+                                             int64_t in_timeoutMillis) {
+    (void)in_timeoutMillis;
+
+    if (in_fds.size() < 1) {
+        return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                "No file descriptor");
+    }
+
+    int fd = in_fds[0].get();
+    if (fd < 0) {
+        return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                "Invalid file descriptor");
+    }
+
+    switch (in_mode) {
+        case IDumpstateDevice::DumpstateMode::FULL:
+            return dumpstateBoardImpl(fd, true);
+
+        case IDumpstateDevice::DumpstateMode::DEFAULT:
+            return dumpstateBoardImpl(fd, false);
+
+        case IDumpstateDevice::DumpstateMode::INTERACTIVE:
+        case IDumpstateDevice::DumpstateMode::REMOTE:
+        case IDumpstateDevice::DumpstateMode::WEAR:
+        case IDumpstateDevice::DumpstateMode::CONNECTIVITY:
+        case IDumpstateDevice::DumpstateMode::WIFI:
+        case IDumpstateDevice::DumpstateMode::PROTO:
+            return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(ERROR_UNSUPPORTED_MODE,
+                                                                           "Unsupported mode");
+
+        default:
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "Invalid mode");
+    }
+
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Dumpstate::getVerboseLoggingEnabled(bool* _aidl_return) {
+    *_aidl_return = getVerboseLoggingEnabledImpl();
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Dumpstate::setVerboseLoggingEnabled(bool in_enable) {
+    ::android::base::SetProperty(kVerboseLoggingProperty, in_enable ? "true" : "false");
+    return ndk::ScopedAStatus::ok();
+}
+
+bool Dumpstate::getVerboseLoggingEnabledImpl() {
+    return ::android::base::GetBoolProperty(kVerboseLoggingProperty, false);
+}
+
+ndk::ScopedAStatus Dumpstate::dumpstateBoardImpl(const int fd, const bool full) {
+    ALOGD("DumpstateDevice::dumpstateBoard() FD: %d\n", fd);
+
+    dprintf(fd, "verbose logging: %s\n", getVerboseLoggingEnabledImpl() ? "enabled" : "disabled");
+    dprintf(fd, "[%s] %s\n", (full ? "full" : "default"), "Hello, world!");
+
+    // Shows an example on how to use the libdumpstateutil API.
+    DumpFileToFd(fd, "cmdline", "/proc/self/cmdline");
+
+    return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace dumpstate
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/dumpstate/aidl/default/Dumpstate.h b/dumpstate/aidl/default/Dumpstate.h
new file mode 100644
index 0000000..0629831
--- /dev/null
+++ b/dumpstate/aidl/default/Dumpstate.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/dumpstate/BnDumpstateDevice.h>
+#include <aidl/android/hardware/dumpstate/IDumpstateDevice.h>
+#include <android/binder_status.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace dumpstate {
+
+class Dumpstate : public BnDumpstateDevice {
+  private:
+    bool getVerboseLoggingEnabledImpl();
+    ::ndk::ScopedAStatus dumpstateBoardImpl(const int fd, const bool full);
+
+  public:
+    ::ndk::ScopedAStatus dumpstateBoard(const std::vector<::ndk::ScopedFileDescriptor>& in_fds,
+                                        IDumpstateDevice::DumpstateMode in_mode,
+                                        int64_t in_timeoutMillis) override;
+
+    ::ndk::ScopedAStatus getVerboseLoggingEnabled(bool* _aidl_return) override;
+
+    ::ndk::ScopedAStatus setVerboseLoggingEnabled(bool in_enable) override;
+};
+
+}  // namespace dumpstate
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/dumpstate/aidl/default/dumpstate-default.rc b/dumpstate/aidl/default/dumpstate-default.rc
new file mode 100644
index 0000000..4d011dd
--- /dev/null
+++ b/dumpstate/aidl/default/dumpstate-default.rc
@@ -0,0 +1,7 @@
+service vendor.dumpstate-default /vendor/bin/hw/android.hardware.dumpstate-service.example
+    class hal
+    user nobody
+    group nobody
+    interface aidl android.hardware.dumpstate.IDumpstateDevice/default
+    oneshot
+    disabled
diff --git a/dumpstate/aidl/default/dumpstate-default.xml b/dumpstate/aidl/default/dumpstate-default.xml
new file mode 100644
index 0000000..877aeed
--- /dev/null
+++ b/dumpstate/aidl/default/dumpstate-default.xml
@@ -0,0 +1,8 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.dumpstate</name>
+        <version>1</version>
+        <fqname>IDumpstateDevice/default</fqname>
+    </hal>
+</manifest>
+
diff --git a/dumpstate/aidl/default/main.cpp b/dumpstate/aidl/default/main.cpp
new file mode 100644
index 0000000..5bc85b4
--- /dev/null
+++ b/dumpstate/aidl/default/main.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Dumpstate.h"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+using aidl::android::hardware::dumpstate::Dumpstate;
+
+int main() {
+    ABinderProcess_setThreadPoolMaxThreadCount(0);
+    std::shared_ptr<Dumpstate> dumpstate = ndk::SharedRefBase::make<Dumpstate>();
+
+    const std::string instance = std::string() + Dumpstate::descriptor + "/default";
+    binder_status_t status =
+            AServiceManager_registerLazyService(dumpstate->asBinder().get(), instance.c_str());
+    CHECK_EQ(status, STATUS_OK);
+
+    ABinderProcess_joinThreadPool();
+    return EXIT_FAILURE;  // Unreachable
+}
diff --git a/dumpstate/aidl/vts/functional/Android.bp b/dumpstate/aidl/vts/functional/Android.bp
new file mode 100644
index 0000000..5e516cf
--- /dev/null
+++ b/dumpstate/aidl/vts/functional/Android.bp
@@ -0,0 +1,41 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//       http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+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: "VtsHalDumpstateTargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    srcs: ["VtsHalDumpstateTargetTest.cpp"],
+    shared_libs: [
+        "libbinder_ndk",
+        "libvintf",
+    ],
+    static_libs: [
+        "android.hardware.dumpstate-V1-ndk",
+    ],
+    test_suites: [
+        "vts",
+    ],
+}
diff --git a/dumpstate/aidl/vts/functional/VtsHalDumpstateTargetTest.cpp b/dumpstate/aidl/vts/functional/VtsHalDumpstateTargetTest.cpp
new file mode 100644
index 0000000..442b0b0
--- /dev/null
+++ b/dumpstate/aidl/vts/functional/VtsHalDumpstateTargetTest.cpp
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <functional>
+#include <tuple>
+#include <vector>
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+
+#include <aidl/android/hardware/dumpstate/IDumpstateDevice.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+using aidl::android::hardware::dumpstate::IDumpstateDevice;
+
+// Base class common to all dumpstate HAL AIDL tests.
+template <typename T>
+class DumpstateAidlTestBase : public ::testing::TestWithParam<T> {
+  protected:
+    bool CheckStatus(const ndk::ScopedAStatus& status, const binder_exception_t expected_ex_code,
+                     const int32_t expected_service_specific) {
+        binder_exception_t ex_code = status.getExceptionCode();
+        if (ex_code != expected_ex_code) {
+            return false;
+        }
+        if (ex_code == EX_SERVICE_SPECIFIC) {
+            int32_t service_specific = status.getServiceSpecificError();
+            if (service_specific != expected_service_specific) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+  public:
+    virtual void SetUp() override { GetService(); }
+
+    virtual std::string GetInstanceName() = 0;
+
+    void GetService() {
+        const std::string instance_name = GetInstanceName();
+
+        ASSERT_TRUE(AServiceManager_isDeclared(instance_name.c_str()));
+        auto dumpstateBinder =
+                ndk::SpAIBinder(AServiceManager_waitForService(instance_name.c_str()));
+        dumpstate = IDumpstateDevice::fromBinder(dumpstateBinder);
+        ASSERT_NE(dumpstate, nullptr) << "Could not get AIDL instance " << instance_name;
+    }
+
+    void ToggleVerboseLogging(bool enable) {
+        ndk::ScopedAStatus status;
+        bool logging_enabled = false;
+
+        status = dumpstate->setVerboseLoggingEnabled(enable);
+        ASSERT_TRUE(status.isOk()) << "Status should be ok: " << status.getDescription();
+
+        status = dumpstate->getVerboseLoggingEnabled(&logging_enabled);
+        ASSERT_TRUE(status.isOk()) << "Status should be ok: " << status.getDescription();
+        ASSERT_EQ(logging_enabled, enable)
+                << "Verbose logging should now be " << (enable ? "enabled" : "disabled");
+    }
+
+    void EnableVerboseLogging() { ToggleVerboseLogging(true); }
+
+    void DisableVerboseLogging() { ToggleVerboseLogging(false); }
+
+    std::shared_ptr<IDumpstateDevice> dumpstate;
+};
+
+// Tests that don't need to iterate every single DumpstateMode value for dumpstateBoard_1_1.
+class DumpstateAidlGeneralTest : public DumpstateAidlTestBase<std::string> {
+  protected:
+    virtual std::string GetInstanceName() override { return GetParam(); }
+};
+
+// Tests that iterate every single DumpstateMode value for dumpstateBoard_1_1.
+class DumpstateAidlPerModeTest
+    : public DumpstateAidlTestBase<std::tuple<std::string, IDumpstateDevice::DumpstateMode>> {
+  protected:
+    virtual std::string GetInstanceName() override { return std::get<0>(GetParam()); }
+
+    IDumpstateDevice::DumpstateMode GetMode() { return std::get<1>(GetParam()); }
+
+    // Will only execute additional_assertions when status == expected.
+    void AssertStatusForMode(const ::ndk::ScopedAStatus& status,
+                             binder_exception_t expected_ex_code, int32_t expected_service_specific,
+                             std::function<void()> additional_assertions = nullptr) {
+        if (GetMode() == IDumpstateDevice::DumpstateMode::DEFAULT) {
+            ASSERT_TRUE(CheckStatus(status, expected_ex_code, expected_ex_code));
+        } else {
+            // The rest of the modes are optional to support, but they MUST return either the
+            // expected value or UNSUPPORTED_MODE.
+            ASSERT_TRUE(CheckStatus(status, expected_ex_code, expected_service_specific) ||
+                        CheckStatus(status, EX_SERVICE_SPECIFIC,
+                                    IDumpstateDevice::ERROR_UNSUPPORTED_MODE));
+        }
+        if (CheckStatus(status, expected_ex_code, expected_service_specific) &&
+            additional_assertions != nullptr) {
+            additional_assertions();
+        }
+    }
+};
+
+constexpr uint64_t kDefaultTimeoutMillis = 30 * 1000;  // 30 seconds
+
+// Negative test: make sure dumpstateBoard() doesn't crash when passed a empty file descriptor
+// array.
+TEST_P(DumpstateAidlPerModeTest, TestNullHandle) {
+    EnableVerboseLogging();
+
+    std::vector<::ndk::ScopedFileDescriptor> dumpstateFds;  // empty file descriptor vector
+
+    auto status = dumpstate->dumpstateBoard(dumpstateFds, GetMode(), kDefaultTimeoutMillis);
+    AssertStatusForMode(status, EX_ILLEGAL_ARGUMENT, 0);
+}
+
+// Positive test: make sure dumpstateBoard() writes something to the FD.
+TEST_P(DumpstateAidlPerModeTest, TestOk) {
+    EnableVerboseLogging();
+
+    // Index 0 corresponds to the read end of the pipe; 1 to the write end.
+    int fds[2];
+    ASSERT_EQ(0, pipe2(fds, O_NONBLOCK)) << errno;
+
+    std::vector<::ndk::ScopedFileDescriptor> dumpstateFds;
+    dumpstateFds.emplace_back(fds[1]);
+
+    auto status = dumpstate->dumpstateBoard(dumpstateFds, GetMode(), kDefaultTimeoutMillis);
+
+    AssertStatusForMode(status, EX_NONE, 0, [&fds]() {
+        // Check that at least one byte was written.
+        char buff;
+        ASSERT_EQ(1, read(fds[0], &buff, 1)) << "Dumped nothing";
+    });
+
+    close(fds[1]);
+    close(fds[0]);
+}
+
+// Positive test: make sure dumpstateBoard() doesn't crash with two FDs.
+TEST_P(DumpstateAidlPerModeTest, TestHandleWithTwoFds) {
+    EnableVerboseLogging();
+
+    int fds1[2];
+    int fds2[2];
+    ASSERT_EQ(0, pipe2(fds1, O_NONBLOCK)) << errno;
+    ASSERT_EQ(0, pipe2(fds2, O_NONBLOCK)) << errno;
+
+    std::vector<::ndk::ScopedFileDescriptor> dumpstateFds;
+    dumpstateFds.emplace_back(fds1[1]);
+    dumpstateFds.emplace_back(fds2[1]);
+
+    auto status = dumpstate->dumpstateBoard(dumpstateFds, GetMode(), kDefaultTimeoutMillis);
+
+    AssertStatusForMode(status, EX_NONE, 0, [&fds1, &fds2]() {
+        // Check that at least one byte was written to one of the FDs.
+        char buff;
+        size_t read1 = read(fds1[0], &buff, 1);
+        size_t read2 = read(fds2[0], &buff, 1);
+        // Sometimes read returns -1, so we can't just add them together and expect >= 1.
+        ASSERT_TRUE(read1 == 1 || read2 == 1) << "Dumped nothing";
+    });
+
+    close(fds1[1]);
+    close(fds1[0]);
+    close(fds2[1]);
+    close(fds2[0]);
+}
+
+// Make sure dumpstateBoard actually validates its arguments.
+TEST_P(DumpstateAidlGeneralTest, TestInvalidModeArgument_Negative) {
+    EnableVerboseLogging();
+
+    int fds[2];
+    ASSERT_EQ(0, pipe2(fds, O_NONBLOCK)) << errno;
+
+    std::vector<::ndk::ScopedFileDescriptor> dumpstateFds;
+    dumpstateFds.emplace_back(fds[1]);
+
+    auto status = dumpstate->dumpstateBoard(dumpstateFds,
+                                            static_cast<IDumpstateDevice::DumpstateMode>(-100),
+                                            kDefaultTimeoutMillis);
+    ASSERT_TRUE(CheckStatus(status, EX_ILLEGAL_ARGUMENT, 0));
+
+    close(fds[1]);
+    close(fds[0]);
+}
+
+TEST_P(DumpstateAidlGeneralTest, TestInvalidModeArgument_Undefined) {
+    EnableVerboseLogging();
+
+    int fds[2];
+    ASSERT_EQ(0, pipe2(fds, O_NONBLOCK)) << errno;
+
+    std::vector<::ndk::ScopedFileDescriptor> dumpstateFds;
+    dumpstateFds.emplace_back(fds[1]);
+
+    auto status = dumpstate->dumpstateBoard(dumpstateFds,
+                                            static_cast<IDumpstateDevice::DumpstateMode>(9001),
+                                            kDefaultTimeoutMillis);
+    ASSERT_TRUE(CheckStatus(status, EX_ILLEGAL_ARGUMENT, 0));
+
+    close(fds[1]);
+    close(fds[0]);
+}
+
+// Make sure disabling verbose logging behaves correctly. Some info is still allowed to be emitted,
+// but it can't have privacy/storage/battery impacts.
+TEST_P(DumpstateAidlPerModeTest, TestDeviceLoggingDisabled) {
+    DisableVerboseLogging();
+
+    // Index 0 corresponds to the read end of the pipe; 1 to the write end.
+    int fds[2];
+    ASSERT_EQ(0, pipe2(fds, O_NONBLOCK)) << errno;
+
+    std::vector<::ndk::ScopedFileDescriptor> dumpstateFds;
+    dumpstateFds.emplace_back(fds[1]);
+
+    auto status = dumpstate->dumpstateBoard(dumpstateFds, GetMode(), kDefaultTimeoutMillis);
+
+    // We don't include additional assertions here about the file passed in. If verbose logging is
+    // disabled, the OEM may choose to include nothing at all, but it is allowed to include some
+    // essential information based on the mode as long as it isn't private user information.
+    AssertStatusForMode(status, EX_NONE, 0);
+
+    close(fds[1]);
+    close(fds[0]);
+}
+
+// Double-enable is perfectly valid, but the second call shouldn't do anything.
+TEST_P(DumpstateAidlGeneralTest, TestRepeatedEnable) {
+    EnableVerboseLogging();
+    EnableVerboseLogging();
+}
+
+// Double-disable is perfectly valid, but the second call shouldn't do anything.
+TEST_P(DumpstateAidlGeneralTest, TestRepeatedDisable) {
+    DisableVerboseLogging();
+    DisableVerboseLogging();
+}
+
+// Toggling in short order is perfectly valid.
+TEST_P(DumpstateAidlGeneralTest, TestRepeatedToggle) {
+    EnableVerboseLogging();
+    DisableVerboseLogging();
+    EnableVerboseLogging();
+    DisableVerboseLogging();
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DumpstateAidlGeneralTest);
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, DumpstateAidlGeneralTest,
+        testing::ValuesIn(android::getAidlHalInstanceNames(IDumpstateDevice::descriptor)),
+        android::PrintInstanceNameToString);
+
+// Includes the mode's name as part of the description string.
+static inline std::string PrintInstanceNameToStringWithMode(
+        const testing::TestParamInfo<std::tuple<std::string, IDumpstateDevice::DumpstateMode>>&
+                info) {
+    return android::PrintInstanceNameToString(
+                   testing::TestParamInfo(std::get<0>(info.param), info.index)) +
+           "_" + toString(std::get<1>(info.param));
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DumpstateAidlPerModeTest);
+INSTANTIATE_TEST_SUITE_P(
+        PerInstanceAndMode, DumpstateAidlPerModeTest,
+        testing::Combine(
+                testing::ValuesIn(android::getAidlHalInstanceNames(IDumpstateDevice::descriptor)),
+                testing::ValuesIn(ndk::internal::enum_values<IDumpstateDevice::DumpstateMode>)),
+        PrintInstanceNameToStringWithMode);
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    ABinderProcess_setThreadPoolMaxThreadCount(1);
+    ABinderProcess_startThreadPool();
+    return RUN_ALL_TESTS();
+}
diff --git a/fastboot/1.0/IFastboot.hal b/fastboot/1.0/IFastboot.hal
index dce3ad7..b39061c 100644
--- a/fastboot/1.0/IFastboot.hal
+++ b/fastboot/1.0/IFastboot.hal
@@ -33,7 +33,7 @@
     /**
      * Executes a fastboot OEM command.
      *
-     * @param oemCmdArgs The oem command that is passed to the fastboot HAL.
+     * @param oemCmd The oem command that is passed to the fastboot HAL.
      * @return result Returns the status SUCCESS if the operation is successful,
      *     INVALID_ARGUMENT for bad arguments,
      *     FAILURE_UNKNOWN for an invalid/unsupported command.
diff --git a/gatekeeper/1.0/vts/functional/VtsHalGatekeeperV1_0TargetTest.cpp b/gatekeeper/1.0/vts/functional/VtsHalGatekeeperV1_0TargetTest.cpp
index e74cca9..f3fa0b4 100644
--- a/gatekeeper/1.0/vts/functional/VtsHalGatekeeperV1_0TargetTest.cpp
+++ b/gatekeeper/1.0/vts/functional/VtsHalGatekeeperV1_0TargetTest.cpp
@@ -236,6 +236,10 @@
   generatePassword(password, 0);
   enrollNewPassword(password, enrollRsp, true);
   verifyPassword(password, enrollRsp.data, 1, verifyRsp, true);
+
+  ALOGI("Testing unenrolled password doesn't verify");
+  generatePassword(password, 1);
+  verifyPassword(password, enrollRsp.data, 1, verifyRsp, false);
   ALOGI("Testing Enroll+Verify done");
 }
 
diff --git a/gnss/1.0/vts/functional/OWNERS b/gnss/1.0/vts/functional/OWNERS
new file mode 100644
index 0000000..b831eb4
--- /dev/null
+++ b/gnss/1.0/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 393449
+yuhany@google.com
diff --git a/gnss/1.1/default/Android.bp b/gnss/1.1/default/Android.bp
index ab87990..3c9c29a 100644
--- a/gnss/1.1/default/Android.bp
+++ b/gnss/1.1/default/Android.bp
@@ -27,7 +27,7 @@
         "android.hardware.gnss@2.0",
         "android.hardware.gnss@1.1",
         "android.hardware.gnss@1.0",
-        "android.hardware.gnss-V1-ndk_platform",
+        "android.hardware.gnss-V1-ndk",
     ],
     static_libs: [
         "android.hardware.gnss@common-default-lib",
diff --git a/gnss/1.1/vts/functional/OWNERS b/gnss/1.1/vts/functional/OWNERS
new file mode 100644
index 0000000..b831eb4
--- /dev/null
+++ b/gnss/1.1/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 393449
+yuhany@google.com
diff --git a/gnss/2.0/default/Android.bp b/gnss/2.0/default/Android.bp
index 8ae9f95..695246a 100644
--- a/gnss/2.0/default/Android.bp
+++ b/gnss/2.0/default/Android.bp
@@ -50,7 +50,7 @@
         "android.hardware.gnss@2.0",
         "android.hardware.gnss@1.1",
         "android.hardware.gnss@1.0",
-        "android.hardware.gnss-V1-ndk_platform",
+        "android.hardware.gnss-V1-ndk",
     ],
     static_libs: [
         "android.hardware.gnss@common-default-lib",
diff --git a/gnss/2.0/vts/functional/OWNERS b/gnss/2.0/vts/functional/OWNERS
new file mode 100644
index 0000000..b831eb4
--- /dev/null
+++ b/gnss/2.0/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 393449
+yuhany@google.com
diff --git a/gnss/2.1/default/Android.bp b/gnss/2.1/default/Android.bp
index 609f59e..c46c735 100644
--- a/gnss/2.1/default/Android.bp
+++ b/gnss/2.1/default/Android.bp
@@ -44,7 +44,7 @@
         "android.hardware.gnss@1.0",
         "android.hardware.gnss@1.1",
         "android.hardware.gnss@2.0",
-        "android.hardware.gnss-V1-ndk_platform",
+        "android.hardware.gnss-V1-ndk",
     ],
     static_libs: [
         "android.hardware.gnss@common-default-lib",
diff --git a/gnss/2.1/vts/functional/OWNERS b/gnss/2.1/vts/functional/OWNERS
new file mode 100644
index 0000000..b831eb4
--- /dev/null
+++ b/gnss/2.1/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 393449
+yuhany@google.com
diff --git a/gnss/aidl/default/Android.bp b/gnss/aidl/default/Android.bp
index 4cc2b6e..c028dd7 100644
--- a/gnss/aidl/default/Android.bp
+++ b/gnss/aidl/default/Android.bp
@@ -52,7 +52,7 @@
         "android.hardware.gnss.measurement_corrections@1.1",
         "android.hardware.gnss.measurement_corrections@1.0",
         "android.hardware.gnss.visibility_control@1.0",
-        "android.hardware.gnss-V1-ndk_platform",
+        "android.hardware.gnss-V1-ndk",
     ],
     srcs: [
         "Gnss.cpp",
diff --git a/gnss/aidl/default/service.cpp b/gnss/aidl/default/service.cpp
index 09f1ad2..bbe34f1 100644
--- a/gnss/aidl/default/service.cpp
+++ b/gnss/aidl/default/service.cpp
@@ -42,7 +42,7 @@
     const std::string instance = std::string() + Gnss::descriptor + "/default";
     binder_status_t status =
             AServiceManager_addService(gnssAidl->asBinder().get(), instance.c_str());
-    CHECK(status == STATUS_OK);
+    CHECK_EQ(status, STATUS_OK);
 
     sp<IGnss> gnss = new GnssHidlHal(gnssAidl);
     configureRpcThreadpool(1, true /* will join */);
diff --git a/gnss/common/utils/default/Android.bp b/gnss/common/utils/default/Android.bp
index 43db873..a1d3123 100644
--- a/gnss/common/utils/default/Android.bp
+++ b/gnss/common/utils/default/Android.bp
@@ -52,6 +52,6 @@
         "android.hardware.gnss@2.1",
         "android.hardware.gnss.measurement_corrections@1.1",
         "android.hardware.gnss.measurement_corrections@1.0",
-        "android.hardware.gnss-V1-ndk_platform",
+        "android.hardware.gnss-V1-ndk",
     ],
 }
diff --git a/gnss/common/utils/default/include/v2_1/GnssTemplate.h b/gnss/common/utils/default/include/v2_1/GnssTemplate.h
index 131af24..48cab99 100644
--- a/gnss/common/utils/default/include/v2_1/GnssTemplate.h
+++ b/gnss/common/utils/default/include/v2_1/GnssTemplate.h
@@ -223,14 +223,8 @@
             this->reportSvStatus(svStatus);
             auto currentLocation = getLocationFromHW();
             notePowerConsumption();
-            if (mGnssFd != -1) {
-                // Only report location if the return from hardware is valid
-                // note that we can not merge these two "if" together, if didn't
-                // get location from hardware, we shouldn't report location, not
-                // report the "default" one.
-                if (currentLocation != nullptr) {
-                    this->reportLocation(*currentLocation);
-                }
+            if (currentLocation != nullptr) {
+                this->reportLocation(*currentLocation);
             } else {
                 if (sGnssCallback_2_1 != nullptr || sGnssCallback_2_0 != nullptr) {
                     const auto location = Utils::getMockLocationV2_0();
diff --git a/graphics/OWNERS b/graphics/OWNERS
new file mode 100644
index 0000000..75ceb23
--- /dev/null
+++ b/graphics/OWNERS
@@ -0,0 +1,9 @@
+# Bug component: 1075130
+
+# Graphics team
+adyabr@google.com
+alecmouri@google.com
+chrisforbes@google.com
+jreck@google.com
+lpy@google.com
+sumir@google.com
\ No newline at end of file
diff --git a/graphics/common/OWNERS b/graphics/common/OWNERS
new file mode 100644
index 0000000..94999ea
--- /dev/null
+++ b/graphics/common/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 1075130
+adyabr@google.com
+alecmouri@google.com
+jreck@google.com
+scroggo@google.com
diff --git a/graphics/common/aidl/Android.bp b/graphics/common/aidl/Android.bp
index 97d7a98..b23d4a7 100644
--- a/graphics/common/aidl/Android.bp
+++ b/graphics/common/aidl/Android.bp
@@ -21,7 +21,7 @@
     ],
     stability: "vintf",
     imports: [
-        "android.hardware.common",
+        "android.hardware.common-V2",
     ],
     backend: {
         java: {
diff --git a/graphics/composer/2.1/default/OWNERS b/graphics/composer/2.1/default/OWNERS
index 709c4d1..331c80d 100644
--- a/graphics/composer/2.1/default/OWNERS
+++ b/graphics/composer/2.1/default/OWNERS
@@ -1,3 +1,4 @@
 # Graphics team
 adyabr@google.com
+alecmouri@google.com
 lpy@google.com
diff --git a/graphics/composer/2.1/default/android.hardware.graphics.composer@2.1-service.rc b/graphics/composer/2.1/default/android.hardware.graphics.composer@2.1-service.rc
index cbd589a..c8fccdc 100644
--- a/graphics/composer/2.1/default/android.hardware.graphics.composer@2.1-service.rc
+++ b/graphics/composer/2.1/default/android.hardware.graphics.composer@2.1-service.rc
@@ -5,4 +5,4 @@
     group graphics drmrpc
     capabilities SYS_NICE
     onrestart restart surfaceflinger
-    writepid /dev/cpuset/system-background/tasks
+    task_profiles ServiceCapacityLow
diff --git a/graphics/composer/2.1/utils/OWNERS b/graphics/composer/2.1/utils/OWNERS
index 7af69b4..83c4f5f 100644
--- a/graphics/composer/2.1/utils/OWNERS
+++ b/graphics/composer/2.1/utils/OWNERS
@@ -1,2 +1,3 @@
 adyabr@google.com
+alecmouri@google.com
 lpy@google.com
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/2.1/vts/OWNERS b/graphics/composer/2.1/vts/OWNERS
index ea06752..a643bbd 100644
--- a/graphics/composer/2.1/vts/OWNERS
+++ b/graphics/composer/2.1/vts/OWNERS
@@ -1,5 +1,6 @@
 # Graphics team
 adyabr@google.com
+alecmouri@google.com
 lpy@google.com
 
 # VTS team
diff --git a/graphics/composer/2.1/vts/functional/Android.bp b/graphics/composer/2.1/vts/functional/Android.bp
index eb67d34..9ffd7d5 100644
--- a/graphics/composer/2.1/vts/functional/Android.bp
+++ b/graphics/composer/2.1/vts/functional/Android.bp
@@ -26,6 +26,7 @@
 cc_test {
     name: "VtsHalGraphicsComposerV2_1TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: ["VtsHalGraphicsComposerV2_1TargetTest.cpp"],
     srcs: ["VtsHalGraphicsComposerV2_1TargetTest.cpp"],
 
     // TODO(b/64437680): Assume these libs are always available on the device.
diff --git a/graphics/composer/2.1/vts/functional/OWNERS b/graphics/composer/2.1/vts/functional/OWNERS
new file mode 100644
index 0000000..3d970d1
--- /dev/null
+++ b/graphics/composer/2.1/vts/functional/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 25423
+adyabr@google.com
+alecmouri@google.com
+sumir@google.com
diff --git a/graphics/composer/2.2/default/OWNERS b/graphics/composer/2.2/default/OWNERS
index 709c4d1..e8f584d 100644
--- a/graphics/composer/2.2/default/OWNERS
+++ b/graphics/composer/2.2/default/OWNERS
@@ -1,3 +1,5 @@
 # Graphics team
 adyabr@google.com
+alecmouri@google.com
 lpy@google.com
+
diff --git a/graphics/composer/2.2/default/android.hardware.graphics.composer@2.2-service.rc b/graphics/composer/2.2/default/android.hardware.graphics.composer@2.2-service.rc
index efe6dad..7714119 100644
--- a/graphics/composer/2.2/default/android.hardware.graphics.composer@2.2-service.rc
+++ b/graphics/composer/2.2/default/android.hardware.graphics.composer@2.2-service.rc
@@ -4,4 +4,4 @@
     group graphics drmrpc
     capabilities SYS_NICE
     onrestart restart surfaceflinger
-    writepid /dev/cpuset/system-background/tasks
+    task_profiles ServiceCapacityLow
diff --git a/graphics/composer/2.2/utils/OWNERS b/graphics/composer/2.2/utils/OWNERS
index 709c4d1..331c80d 100644
--- a/graphics/composer/2.2/utils/OWNERS
+++ b/graphics/composer/2.2/utils/OWNERS
@@ -1,3 +1,4 @@
 # Graphics team
 adyabr@google.com
+alecmouri@google.com
 lpy@google.com
diff --git a/graphics/composer/2.2/vts/functional/Android.bp b/graphics/composer/2.2/vts/functional/Android.bp
index 36f3c00..e45696d 100644
--- a/graphics/composer/2.2/vts/functional/Android.bp
+++ b/graphics/composer/2.2/vts/functional/Android.bp
@@ -30,6 +30,10 @@
         // Needed for librenderengine
         "skia_deps",
     ],
+    tidy_timeout_srcs: [
+        "VtsHalGraphicsComposerV2_2ReadbackTest.cpp",
+        "VtsHalGraphicsComposerV2_2TargetTest.cpp",
+    ],
     srcs: [
         "VtsHalGraphicsComposerV2_2ReadbackTest.cpp",
         "VtsHalGraphicsComposerV2_2TargetTest.cpp",
diff --git a/graphics/composer/2.2/vts/functional/OWNERS b/graphics/composer/2.2/vts/functional/OWNERS
index ea06752..a4eb0ca 100644
--- a/graphics/composer/2.2/vts/functional/OWNERS
+++ b/graphics/composer/2.2/vts/functional/OWNERS
@@ -1,7 +1,6 @@
+# Bug component: 25423
 # Graphics team
 adyabr@google.com
+alecmouri@google.com
 lpy@google.com
-
-# VTS team
-yim@google.com
-zhuoyao@google.com
+sumir@google.com
diff --git a/graphics/composer/2.3/default/OWNERS b/graphics/composer/2.3/default/OWNERS
index 709c4d1..331c80d 100644
--- a/graphics/composer/2.3/default/OWNERS
+++ b/graphics/composer/2.3/default/OWNERS
@@ -1,3 +1,4 @@
 # Graphics team
 adyabr@google.com
+alecmouri@google.com
 lpy@google.com
diff --git a/graphics/composer/2.3/default/android.hardware.graphics.composer@2.3-service.rc b/graphics/composer/2.3/default/android.hardware.graphics.composer@2.3-service.rc
index 81ce890..d3835a4 100644
--- a/graphics/composer/2.3/default/android.hardware.graphics.composer@2.3-service.rc
+++ b/graphics/composer/2.3/default/android.hardware.graphics.composer@2.3-service.rc
@@ -4,4 +4,4 @@
     group graphics drmrpc
     capabilities SYS_NICE
     onrestart restart surfaceflinger
-    writepid /dev/cpuset/system-background/tasks
+    task_profiles ServiceCapacityLow
diff --git a/graphics/composer/2.3/utils/OWNERS b/graphics/composer/2.3/utils/OWNERS
index 709c4d1..331c80d 100644
--- a/graphics/composer/2.3/utils/OWNERS
+++ b/graphics/composer/2.3/utils/OWNERS
@@ -1,3 +1,4 @@
 # Graphics team
 adyabr@google.com
+alecmouri@google.com
 lpy@google.com
diff --git a/graphics/composer/2.3/vts/functional/Android.bp b/graphics/composer/2.3/vts/functional/Android.bp
index d27a151..70384ac 100644
--- a/graphics/composer/2.3/vts/functional/Android.bp
+++ b/graphics/composer/2.3/vts/functional/Android.bp
@@ -26,6 +26,7 @@
 cc_test {
     name: "VtsHalGraphicsComposerV2_3TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: ["VtsHalGraphicsComposerV2_3TargetTest.cpp"],
     srcs: ["VtsHalGraphicsComposerV2_3TargetTest.cpp"],
 
     // TODO(b/64437680): Assume these libs are always available on the device.
diff --git a/graphics/composer/2.3/vts/functional/OWNERS b/graphics/composer/2.3/vts/functional/OWNERS
index ea06752..a4eb0ca 100644
--- a/graphics/composer/2.3/vts/functional/OWNERS
+++ b/graphics/composer/2.3/vts/functional/OWNERS
@@ -1,7 +1,6 @@
+# Bug component: 25423
 # Graphics team
 adyabr@google.com
+alecmouri@google.com
 lpy@google.com
-
-# VTS team
-yim@google.com
-zhuoyao@google.com
+sumir@google.com
diff --git a/graphics/composer/2.4/IComposerClient.hal b/graphics/composer/2.4/IComposerClient.hal
index 1a59bbd..9e3cf0e 100644
--- a/graphics/composer/2.4/IComposerClient.hal
+++ b/graphics/composer/2.4/IComposerClient.hal
@@ -34,9 +34,7 @@
         /**
          * The configuration group ID (as int32_t) this config is associated to.
          * Switching between configurations within the same group may be done seamlessly
-         * in some conditions via setActiveConfigWithConstraints. Configurations which
-         * share the same config group are similar in all attributes except for the
-         * vsync period.
+         * in some conditions via setActiveConfigWithConstraints.
          */
         CONFIG_GROUP = 7,
     };
diff --git a/graphics/composer/2.4/default/OWNERS b/graphics/composer/2.4/default/OWNERS
index 709c4d1..331c80d 100644
--- a/graphics/composer/2.4/default/OWNERS
+++ b/graphics/composer/2.4/default/OWNERS
@@ -1,3 +1,4 @@
 # Graphics team
 adyabr@google.com
+alecmouri@google.com
 lpy@google.com
diff --git a/graphics/composer/2.4/default/android.hardware.graphics.composer@2.4-service.rc b/graphics/composer/2.4/default/android.hardware.graphics.composer@2.4-service.rc
index a296b0a..d82dcd9 100644
--- a/graphics/composer/2.4/default/android.hardware.graphics.composer@2.4-service.rc
+++ b/graphics/composer/2.4/default/android.hardware.graphics.composer@2.4-service.rc
@@ -4,4 +4,4 @@
     group graphics drmrpc
     capabilities SYS_NICE
     onrestart restart surfaceflinger
-    writepid /dev/cpuset/system-background/tasks
+    task_profiles ServiceCapacityLow
diff --git a/graphics/composer/2.4/utils/OWNERS b/graphics/composer/2.4/utils/OWNERS
index 709c4d1..331c80d 100644
--- a/graphics/composer/2.4/utils/OWNERS
+++ b/graphics/composer/2.4/utils/OWNERS
@@ -1,3 +1,4 @@
 # Graphics team
 adyabr@google.com
+alecmouri@google.com
 lpy@google.com
diff --git a/graphics/composer/2.4/vts/functional/Android.bp b/graphics/composer/2.4/vts/functional/Android.bp
index 6089e2d..22ae7c4 100644
--- a/graphics/composer/2.4/vts/functional/Android.bp
+++ b/graphics/composer/2.4/vts/functional/Android.bp
@@ -26,6 +26,7 @@
 cc_test {
     name: "VtsHalGraphicsComposerV2_4TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: ["VtsHalGraphicsComposerV2_4TargetTest.cpp"],
     srcs: ["VtsHalGraphicsComposerV2_4TargetTest.cpp"],
 
     // TODO(b/64437680): Assume these libs are always available on the device.
diff --git a/graphics/composer/2.4/vts/functional/OWNERS b/graphics/composer/2.4/vts/functional/OWNERS
index ea06752..a4eb0ca 100644
--- a/graphics/composer/2.4/vts/functional/OWNERS
+++ b/graphics/composer/2.4/vts/functional/OWNERS
@@ -1,7 +1,6 @@
+# Bug component: 25423
 # Graphics team
 adyabr@google.com
+alecmouri@google.com
 lpy@google.com
-
-# VTS team
-yim@google.com
-zhuoyao@google.com
+sumir@google.com
diff --git a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
index b071f71..fa294ff 100644
--- a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
+++ b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
@@ -161,7 +161,8 @@
         return mGralloc->allocate(
                 width, height, /*layerCount*/ 1,
                 static_cast<common::V1_1::PixelFormat>(PixelFormat::RGBA_8888),
-                static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN));
+                static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN |
+                                      BufferUsage::COMPOSER_OVERLAY));
     }
 
     struct TestParameters {
diff --git a/graphics/mapper/2.0/vts/OWNERS b/graphics/mapper/2.0/vts/OWNERS
index 4177296..62e3f2a 100644
--- a/graphics/mapper/2.0/vts/OWNERS
+++ b/graphics/mapper/2.0/vts/OWNERS
@@ -1,8 +1,5 @@
-# Graphics team
+# Bug component: 25423
 chrisforbes@google.com
 jreck@google.com
 lpy@google.com
-
-# VTS team
-yim@google.com
-zhuoyao@google.com
+sumir@google.com
diff --git a/graphics/mapper/2.1/vts/OWNERS b/graphics/mapper/2.1/vts/OWNERS
index 4177296..43c018a 100644
--- a/graphics/mapper/2.1/vts/OWNERS
+++ b/graphics/mapper/2.1/vts/OWNERS
@@ -1,8 +1,2 @@
-# Graphics team
-chrisforbes@google.com
-jreck@google.com
-lpy@google.com
-
-# VTS team
-yim@google.com
-zhuoyao@google.com
+# Bug component: 25423
+include ../../2.0/vts/OWNERS
diff --git a/graphics/mapper/3.0/vts/OWNERS b/graphics/mapper/3.0/vts/OWNERS
index c9f24d0..43c018a 100644
--- a/graphics/mapper/3.0/vts/OWNERS
+++ b/graphics/mapper/3.0/vts/OWNERS
@@ -1,4 +1,2 @@
-# Graphics team
-chrisforbes@google.com
-jreck@google.com
-lpy@google.com
+# Bug component: 25423
+include ../../2.0/vts/OWNERS
diff --git a/graphics/mapper/4.0/vts/OWNERS b/graphics/mapper/4.0/vts/OWNERS
index c9f24d0..43c018a 100644
--- a/graphics/mapper/4.0/vts/OWNERS
+++ b/graphics/mapper/4.0/vts/OWNERS
@@ -1,4 +1,2 @@
-# Graphics team
-chrisforbes@google.com
-jreck@google.com
-lpy@google.com
+# Bug component: 25423
+include ../../2.0/vts/OWNERS
diff --git a/graphics/mapper/4.0/vts/functional/Android.bp b/graphics/mapper/4.0/vts/functional/Android.bp
index 11ebdc5..032bc0f 100644
--- a/graphics/mapper/4.0/vts/functional/Android.bp
+++ b/graphics/mapper/4.0/vts/functional/Android.bp
@@ -28,7 +28,7 @@
     defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalGraphicsMapperV4_0TargetTest.cpp"],
     static_libs: [
-        "android.hardware.graphics.common-V2-ndk_platform",
+        "android.hardware.graphics.common-V2-ndk",
         "android.hardware.graphics.mapper@4.0-vts",
         "libgralloctypes",
         "libsync",
diff --git a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
index f55a6b7..61277ee 100644
--- a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
+++ b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
@@ -2001,6 +2001,11 @@
               mGralloc->set(bufferHandle, gralloc4::MetadataType_Dataspace, vec));
     ASSERT_EQ(Error::UNSUPPORTED,
               mGralloc->set(bufferHandle, gralloc4::MetadataType_BlendMode, vec));
+
+    // Keep optional metadata types below and populate the encoded metadata vec
+    // with some arbitrary different metadata because the common gralloc4::decode*()
+    // functions do not distinguish between an empty vec and bad value.
+    ASSERT_EQ(NO_ERROR, gralloc4::encodeDataspace(Dataspace::SRGB_LINEAR, &vec));
     ASSERT_EQ(Error::UNSUPPORTED,
               mGralloc->set(bufferHandle, gralloc4::MetadataType_Smpte2086, vec));
     ASSERT_EQ(Error::UNSUPPORTED,
diff --git a/health/2.0/utils/libhealthhalutils/HealthHalUtils.cpp b/health/2.0/utils/libhealthhalutils/HealthHalUtils.cpp
index 9e1cc70..3c353e6 100644
--- a/health/2.0/utils/libhealthhalutils/HealthHalUtils.cpp
+++ b/health/2.0/utils/libhealthhalutils/HealthHalUtils.cpp
@@ -25,7 +25,26 @@
 namespace V2_0 {
 
 sp<IHealth> get_health_service() {
-    for (auto&& instanceName : {"default", "backup"}) {
+    // For the core and vendor variant, the "backup" instance points to healthd,
+    // which is removed.
+    // For the recovery variant, the "backup" instance has a different
+    // meaning. It points to android.hardware.health@2.0-impl-default.recovery
+    // which was assumed by OEMs to be always installed when a
+    // vendor-specific libhealthd is not necessary. Hence, its behavior
+    // is kept. See health/2.0/README.md.
+    // android.hardware.health@2.0-impl-default.recovery, and subsequently the
+    // special handling of recovery mode below, can be removed once health@2.1
+    // is the minimum required version (i.e. compatibility matrix level 5 is the
+    // minimum supported level). Health 2.1 requires OEMs to install the
+    // implementation to the recovery partition when it is necessary (i.e. on
+    // non-A/B devices, where IsBatteryOk() is needed in recovery).
+    for (auto&& instanceName :
+#ifdef __ANDROID_RECOVERY__
+         { "default", "backup" }
+#else
+         {"default"}
+#endif
+    ) {
         auto ret = IHealth::getService(instanceName);
         if (ret != nullptr) {
             return ret;
diff --git a/health/2.0/vts/OWNERS b/health/2.0/vts/OWNERS
index 4024ec0..9f96f51 100644
--- a/health/2.0/vts/OWNERS
+++ b/health/2.0/vts/OWNERS
@@ -1,5 +1,3 @@
+# Bug component: 30545
 elsk@google.com
 sspatil@google.com
-
-# VTS team
-yim@google.com
diff --git a/health/2.0/vts/functional/Android.bp b/health/2.0/vts/functional/Android.bp
index eb69612..597fb50 100644
--- a/health/2.0/vts/functional/Android.bp
+++ b/health/2.0/vts/functional/Android.bp
@@ -26,11 +26,18 @@
 cc_test {
     name: "VtsHalHealthV2_0TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: ["VtsHalHealthV2_0TargetTest.cpp"],
     srcs: ["VtsHalHealthV2_0TargetTest.cpp"],
     static_libs: [
         "libgflags",
         "android.hardware.health@1.0",
         "android.hardware.health@2.0",
     ],
-    test_suites: ["general-tests", "vts"],
+    header_libs: [
+        "libhealthtest_headers",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
 }
diff --git a/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp b/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp
index 7fabf2b..3afba45 100644
--- a/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp
+++ b/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp
@@ -29,6 +29,7 @@
 #include <android/hardware/health/2.0/types.h>
 #include <gflags/gflags.h>
 #include <gtest/gtest.h>
+#include <health-test/TestUtils.h>
 #include <hidl/GtestPrinter.h>
 #include <hidl/ServiceManagement.h>
 #include <log/log.h>
@@ -51,6 +52,7 @@
 namespace hardware {
 namespace health {
 
+using test_utils::SucceedOnce;
 using V1_0::BatteryStatus;
 using V1_0::toString;
 
@@ -356,64 +358,9 @@
                                   << toString(current.result) << ", skipping";
     }
 
-    // For IHealth.getCurrentNow/Average, if current is not available, it is expected that
-    // current.result == Result::NOT_SUPPORTED, which is checked above. Hence, zero current is
-    // not treated as unknown values.
-    // For IHealth.getHealthInfo, if current is not available, health_info.current_* == 0.
-    // Caller of this function provides current.result == Result::SUCCESS. Hence, just skip the
-    // check.
-    if (current.value == 0 && acceptZeroCurrentAsUnknown) {
-        return AssertionSuccess()
-               << "current is 0, which indicates the value may not be available. Skipping.";
-    }
-
-    switch (status.value) {
-        case BatteryStatus::UNKNOWN:
-            if (current.value != 0) {
-                // BatteryStatus may be UNKNOWN initially with a non-zero current value, but
-                // after it is initialized, it should be known.
-                return AssertionFailure()
-                       << "BatteryStatus is UNKNOWN but current is not 0. Actual: "
-                       << current.value;
-            }
-            break;
-        case BatteryStatus::CHARGING:
-            if (current.value <= 0) {
-                return AssertionFailure()
-                       << "BatteryStatus is CHARGING but current is not positive. Actual: "
-                       << current.value;
-            }
-            break;
-        case BatteryStatus::NOT_CHARGING:
-            if (current.value > 0) {
-                return AssertionFailure() << "BatteryStatus is " << toString(status.value)
-                                          << " but current is positive. Actual: " << current.value;
-            }
-            break;
-        case BatteryStatus::DISCHARGING:
-            if (current.value >= 0) {
-                return AssertionFailure()
-                       << "BatteryStatus is " << toString(status.value)
-                       << " but current is not negative. Actual: " << current.value;
-            }
-            break;
-        case BatteryStatus::FULL:
-            // Battery current may be positive or negative depending on the load.
-            break;
-        default:
-            return AssertionFailure() << "Unknown BatteryStatus " << toString(status.value);
-    }
-
-    return AssertionSuccess() << "BatteryStatus is " << toString(status.value)
-                              << " and current has the correct sign: " << current.value;
-}
-
-static AssertionResult IsValueSimilar(int32_t dividend, int32_t divisor, double factor) {
-    auto difference = abs(dividend - divisor);
-    if (difference > factor * abs(divisor)) {
-        return AssertionFailure() << dividend << " and " << divisor << " are not similar.";
-    }
-    return AssertionSuccess() << dividend << " and " << divisor << " are similar.";
+    return test_utils::IsBatteryCurrentSignCorrect(
+            status.value, current.value, acceptZeroCurrentAsUnknown,
+            [](BatteryStatus status) { return toString(status); });
 }
 
 static AssertionResult IsBatteryCurrentSimilar(HalResult<BatteryStatus> status,
@@ -437,31 +384,8 @@
                                   << currentAverage.value << ", skipping";
     }
 
-    // Check that the two values are similar. Note that the two tests uses a different
-    // divisor to ensure that they are actually pretty similar. For example,
-    // IsValueSimilar(5,10,0.4) returns true, but IsValueSimlar(10,5,0.4) returns false.
-    TEST_AND_RETURN(IsValueSimilar(currentNow.value, currentAverage.value, gCurrentCompareFactor)
-                    << " for now vs. average. Check units.");
-    TEST_AND_RETURN(IsValueSimilar(currentAverage.value, currentNow.value, gCurrentCompareFactor)
-                    << " for average vs. now. Check units.");
-    return AssertionSuccess() << "currentNow = " << currentNow.value
-                              << " and currentAverage = " << currentAverage.value
-                              << " are considered similar.";
-}
-
-// Test that f() returns AssertionSuccess() once in a given period of time.
-template <typename Duration, typename Function>
-static AssertionResult SucceedOnce(Duration d, Function f) {
-    AssertionResult result = AssertionFailure() << "Function never evaluated.";
-    auto end = std::chrono::system_clock::now() + d;
-    while (std::chrono::system_clock::now() <= end) {
-        result = f();
-        if (result) {
-            return result;
-        }
-        std::this_thread::sleep_for(2s);
-    }
-    return result;
+    return test_utils::IsBatteryCurrentSimilar(currentNow.value, currentAverage.value,
+                                               gCurrentCompareFactor);
 }
 
 uint64_t GetShippingApiLevel() {
@@ -603,40 +527,8 @@
     }
 
     const auto& batteryInfo = healthInfo.value.legacy;
-    bool isConnected = batteryInfo.chargerAcOnline || batteryInfo.chargerUsbOnline ||
-                       batteryInfo.chargerWirelessOnline;
-
-    std::stringstream message;
-    message << "BatteryStatus is " << toString(status.value) << " and "
-            << (isConnected ? "" : "no ")
-            << "power source is connected: ac=" << batteryInfo.chargerAcOnline
-            << ", usb=" << batteryInfo.chargerUsbOnline
-            << ", wireless=" << batteryInfo.chargerWirelessOnline;
-
-    switch (status.value) {
-        case BatteryStatus::UNKNOWN: {
-            // Don't enforce anything on isConnected on unknown battery status.
-            // Battery-less devices must report UNKNOWN battery status, but may report true
-            // or false on isConnected.
-        } break;
-        case BatteryStatus::CHARGING:
-        case BatteryStatus::NOT_CHARGING:
-        case BatteryStatus::FULL: {
-            if (!isConnected) {
-                return AssertionFailure() << message.str();
-            }
-        } break;
-        case BatteryStatus::DISCHARGING: {
-            if (isConnected) {
-                return AssertionFailure() << message.str();
-            }
-        } break;
-        default: {
-            return AssertionFailure() << "Unknown battery status value " << toString(status.value);
-        } break;
-    }
-
-    return AssertionSuccess() << message.str();
+    return test_utils::IsBatteryStatusCorrect(
+            status.value, batteryInfo, [](BatteryStatus status) { return toString(status); });
 }
 
 TEST_P(BatteryTest, ConnectedAgainstStatusFromHal) {
diff --git a/health/2.1/vts/OWNERS b/health/2.1/vts/OWNERS
index 20450ba..a6803cd 100644
--- a/health/2.1/vts/OWNERS
+++ b/health/2.1/vts/OWNERS
@@ -1,3 +1,2 @@
 elsk@google.com
-hridya@google.com
 sspatil@google.com
diff --git a/health/2.1/vts/functional/OWNERS b/health/2.1/vts/functional/OWNERS
new file mode 100644
index 0000000..cd06415
--- /dev/null
+++ b/health/2.1/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 30545
+elsk@google.com
diff --git a/health/aidl/Android.bp b/health/aidl/Android.bp
new file mode 100644
index 0000000..86bca69
--- /dev/null
+++ b/health/aidl/Android.bp
@@ -0,0 +1,80 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+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.health",
+    vendor_available: true,
+    recovery_available: true,
+    host_supported: true,
+    srcs: ["android/hardware/health/*.aidl"],
+    stability: "vintf",
+    backend: {
+        cpp: {
+            enabled: false,
+        },
+        java: {
+            enabled: true,
+            sdk_version: "module_current",
+        },
+        ndk: {
+            vndk: {
+                enabled: true,
+            },
+        },
+    },
+}
+
+cc_library {
+    name: "android.hardware.health-translate-ndk",
+    vendor_available: true,
+    recovery_available: true,
+    host_supported: true,
+    srcs: ["android/hardware/health/translate-ndk.cpp"],
+    shared_libs: [
+        "libbinder_ndk",
+        "libhidlbase",
+        "android.hardware.health-V1-ndk",
+        "android.hardware.health@2.0",
+        "android.hardware.health@2.1",
+    ],
+    export_include_dirs: ["include"],
+    export_shared_lib_headers: [
+        "android.hardware.health@2.0",
+        "android.hardware.health@2.1",
+    ],
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
+}
+
+java_library {
+    name: "android.hardware.health-translate-java",
+    srcs: ["android/hardware/health/Translate.java"],
+    libs: [
+        "android.hardware.health-V1-java",
+        "android.hardware.health-V2.0-java",
+        "android.hardware.health-V2.1-java",
+    ],
+}
diff --git a/health/aidl/OWNERS b/health/aidl/OWNERS
new file mode 100644
index 0000000..fcad499
--- /dev/null
+++ b/health/aidl/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 30545
+elsk@google.com
+smoreland@google.com
+stayfan@google.com
diff --git a/health/aidl/README.md b/health/aidl/README.md
new file mode 100644
index 0000000..54d6758
--- /dev/null
+++ b/health/aidl/README.md
@@ -0,0 +1,330 @@
+# Health AIDL HAL
+
+## Determine whether the example service implementation is sufficient {#determine}
+
+You need a custom implementation if any of the following is true:
+
+* You are migrating from a custom
+  [health 2.1 HIDL HAL implementation](../2.1/README.md).
+* System properties `ro.charger.enable_suspend` and/or `ro.charger.no_ui`
+  are set to a `true` value. See [below](#charger-sysprops).
+* The device supports offline charging mode, and the `service`
+  declaration with `class charger` in `init.rc` is different from the one
+  provided by the example implementation. See [below](#charger-init-rc).
+
+If the example HAL service is sufficient, [install it](#use-example). Otherwise,
+[implement a custom HAL service](#use-custom).
+
+### System properties for charger {#charger-sysprops}
+
+The health AIDL HAL service also provides functionalities of `charger`. As a
+result, the system charger at `/system/bin/charger` is deprecated.
+
+However, the health AIDL HAL service is not allowed to read `ro.charger.*`
+system properties. These properties include:
+* `ro.charger.enable_suspend`. If set, you need a custom health AIDL HAL
+  service. See [below](#charger-enable-suspend).
+* `ro.charger.no_ui`. If set, you need a custom health AIDL HAL service.
+  See [below](#charger-no-ui).
+* `ro.charger.draw_split_screen`. The system property is deprecated.
+* `ro.charger.draw_split_offset`. The system property is deprecated.
+* `ro.charger.disable_init_blank`. The system property is deprecated.
+
+If you need to set any of the deprecated system properties, contact
+[OWNERS](OWNERS).
+
+### Default `service` declaration for charger in `init.rc` {#charger-init-rc}
+
+See
+[android.hardware.health-service.example.rc](default/android.hardware.health-service.example.rc).
+
+Check the `service` declaration in your device-specific `init.rc` file that
+has `class charger`. Most likely, the declaration looks something like this
+(Below is an excerpt from Pixel 3):
+
+```text
+service vendor.charger /system/bin/charger
+    class charger
+    seclabel u:r:charger:s0
+    user system
+    group system wakelock input
+    capabilities SYS_BOOT
+    file /dev/kmsg w
+    file /sys/fs/pstore/console-ramoops-0 r
+    file /sys/fs/pstore/console-ramoops r
+    file /proc/last_kmsg r
+```
+
+Compare each line against the one provided by the example health AIDL HAL
+service in
+[android.hardware.health-service.example.rc](default/android.hardware.health-service.example.rc).
+Specifically:
+
+* For the `service` line, if the name of the service is **NOT**
+  `vendor.charger`, and there are actions
+  in the rc file triggered by `on property:init.svc.<name>=running` where
+  `<name>` is the name of your charger service, then you need a custom health
+  AIDL service.
+* If your service belongs to additional classes beside `charger`, you need a
+  custom health AIDL service.
+* Modify the `seclabel` line. Replace `charger` with `charger_vendor`.
+* If your service has a different `user` (not `system`), you need a custom
+  health AIDL service.
+* If your service belongs to additional `group`s beside
+  `system wakelock input`, you need a custom health AIDL service.
+* If your service requires additional capabilities beside `SYS_BOOT`,
+  you need a custom health AIDL service.
+* If your service requires additional `file`s to be opened prior to execution,
+  you need a custom health AIDL service.
+
+## Using the example health AIDL HAL service {#use-example}
+
+If you [determined](#determine) that the example health AIDL HAL service works
+for your device, install it with
+
+```mk
+PRODUCT_PACKAGES += \
+    android.hardware.health-service.example \
+    android.hardware.health-service.example_recovery \
+```
+
+Then, delete any existing `service` with `class charger` in your device-specific
+`init.rc` files, because
+[android.hardware.health-service.example.rc](default/android.hardware.health-service.example.rc)
+already contains an entry for charger.
+
+If your device supports charger mode and it has custom charger resources,
+[move charger resources to `/vendor`](#charger-res)
+
+## Implementing a custom health AIDL HAL service {#use-custom}
+
+### Override the `Health` class {#health-impl}
+
+See [`Health.h`](default/include/health-impl/Health.h) for its class
+declaration. Inherit the class to customize for your device.
+
+```c++
+namespace aidl::android::hardware::health {
+class HealthImpl : public Health {
+    // ...
+};
+} // namespace aidl::android::hardware::health
+int main(int, char**) {
+    // ...
+    auto binder = ndk::SharedRefBase::make<aidl::android::hardware::health::HealthImpl>(
+            "default", std::move(config));
+    // ...
+}
+```
+
+* The logic to modify `healthd_config`, traditionally in `healthd_board_init()`
+  should be called before passing the `healthd_config` struct to your
+  `HealthImpl` class in [`main()`](#main).
+
+* The following functions are similar to the ones in the health 2.1 HIDL HAL:
+
+| AIDL implementation                 | HIDL implementation         |
+|-------------------------------------|-----------------------------|
+| `Health::getChargeCounterUah`       | `Health::getChargeCounter`  |
+| `Health::getCurrentNowMicroamps`    | `Health::getCurrentNow`     |
+| `Health::getCurrentAverageMicroamps`| `Health::getCurrentAverage` |
+| `Health::getCapacity`               | `Health::getCapacity`       |
+| `Health::getChargeStatus`           | `Health::getChargeStatus`   |
+| `Health::getEnergyCounterNwh`       | `Health::getEnergyCounter`  |
+| `Health::getDiskStats`              | `Health::getDiskStats`      |
+| `Health::getStorageInfo`            | `Health::getStorageInfo`    |
+| `Health::BinderEvent`               | `BinderHealth::BinderEvent` |
+| `Health::dump`                      | `Health::debug`             |
+| `Health::ShouldKeepScreenOn`        | `Health::shouldKeepScreenOn`|
+| `Health::UpdateHealthInfo`          | `Health::UpdateHealthInfo`  |
+
+### Implement `main()` {#main}
+
+See the [`main.cpp`](default/main.cpp) for the example health AIDL service for
+an example.
+
+If you need to modify `healthd_config`, do it before passing it to the
+constructor of `HealthImpl` (or `Health` if you did not implement a subclass
+of it).
+
+```c++
+int main(int argc, char** argv) {
+    auto config = std::make_unique<healthd_config>();
+    ::android::hardware::health::InitHealthdConfig(config.get());
+    healthd_board_init(config.get());
+    auto binder = ndk::SharedRefBase::make<Health>("default", std::move(config));
+    // ...
+}
+```
+
+If your device does not support off-line charging mode, or does not have a UI
+for charger (`ro.charger.no_ui=true`), skip the invocation of
+`ChargerModeMain()` in `main()`.
+
+### Build system changes
+
+Install both the platform and recovery variant of the service. For example:
+
+```mk
+PRODUCT_PACKAGES += \
+    android.hardware.health-service.cuttlefish \
+    android.hardware.health-service.cuttlefish_recovery \
+```
+
+### SELinux rules
+
+Add device specific permissions to the domain where the health HAL
+process is executed, especially if a device-specific `libhealthd` is used
+and/or device-specific storage related APIs are implemented.
+
+Example (assuming that your health AIDL service runs in domain
+`hal_health_tuna`:
+
+```text
+type hal_health_tuna, domain;
+hal_server_domain(hal_health_tuna, hal_health)
+type hal_health_tuna_exec, exec_type, vendor_file_type, file_type;
+
+# allow hal_health_tuna ...;
+```
+
+If you did not define a separate domain, the domain is likely
+`hal_health_default`. The device-specific rules for it is likely at
+`device/<manufacturer>/<device>/sepolicy/vendor/hal_health_default.te`.
+In this case, the aforementioned SELinux rules and types has already been
+defined. You only need to add device-specific permissions.
+
+```text
+# allow hal_health_default ...;
+```
+
+### Implementing charger {#charger}
+
+#### Move charger resources to `/vendor`
+
+Ensure that charger resources are installed to `/vendor`, not `/product`.
+
+`animation.txt` must be moved to the following location:
+
+```text
+/vendor/etc/res/values/charger/animation.txt
+```
+
+Charger resources in `/system` is not read by the health HAL service in
+`/vendor`. Specifically, resources should be installed to the following
+location:
+
+```
+/vendor/etc/res/images/charger/*.png
+```
+
+If resources are not found in these locations, the health HAL service falls
+back to the following locations:
+
+```
+/vendor/etc/res/images/charger/default/*.png
+```
+
+You can use the default resources by installing the default module:
+
+```makefile
+PRODUCT_PACKAGES += charger_res_images_vendor
+```
+
+#### Modify `init.rc` for charger
+
+It is recommended that you move the existing `service` entry with
+`class charger` to the `init.rc` file in your custom health service.
+
+If there are existing actions in the rc file triggered by
+`on property:init.svc.<name>=running`, where `<name>` is the name of your
+existing charger service (usually `vendor.charger`), then the name of the
+service must be kept as-is. If you modify the name of the service, the actions
+are not triggered properly.
+
+Modify the entry to invoke the health service binary with `--charger` argument.
+See
+[android.hardware.health-service.example.rc](default/android.hardware.health-service.example.rc)
+for an example:
+
+```text
+service vendor.charger /vendor/bin/hw/android.hardware.health-service-tuna --charger
+    class charger
+    seclabel u:r:charger_vendor:s0
+    # ...
+```
+
+#### No charger mode {#no-charger}
+
+If your device does not support off-line charging mode, skip the invocation of
+`ChargerModeMain()` in `main()`.
+
+```c++
+int main(int, char**) {
+    // ...
+    // Skip checking if arguments contain "--charger"
+    auto hal_health_loop = std::make_shared<HalHealthLoop>(binder, binder);
+    return hal_health_loop->StartLoop();
+}
+```
+
+You may optionally delete the `service` entry with `class charger` in the
+`init.rc` file.
+
+#### No charger UI {#charger-no-ui}
+
+If your device does not have a UI for charger (`ro.charger.no_ui=true`), skip
+the invocation of `ChargerModeMain()` in `main()`.
+
+You may want to keep the `KernelLogger` so that charger still logs battery
+information to the kernel logs.
+
+```c++
+int main(int argc, char** argv) {
+    // ...
+    if (argc >= 2 && argv[1] == "--charger"sv) {
+        android::base::InitLogging(argv, &android::base::KernelLogger);
+        // fallthrough to HalHealthLoop::StartLoop()
+    }
+    auto hal_health_loop = std::make_shared<HalHealthLoop>(binder, binder);
+    return hal_health_loop->StartLoop();
+}
+```
+
+#### Enable suspend {#charger-enable-suspend}
+
+If your device has `ro.charger.enable_suspend=true`, implement a new class,
+`ChargerCallbackImpl`, that inherits from
+[`ChargerCallback`](default/include/health-impl/ChargerUtils.h). Then
+override the `ChargerEnableSuspend` function to return `true`. Then pass an
+instance of `ChargerCallbackImpl` to `ChargerModeMain()` instead.
+
+```c++
+namespace aidl::android::hardware::health {
+class ChargerCallbackImpl : public ChargerCallback {
+    bool ChargerEnableSuspend() override { return true; }
+};
+} // namespace aidl::android::hardware::health
+int main(int argc, char** argv) {
+    // ...
+    if (argc >= 2 && argv[1] == "--charger"sv) {
+        android::base::InitLogging(argv, &android::base::KernelLogger);
+#if !CHARGER_FORCE_NO_UI
+        return ChargerModeMain(binder,
+                std::make_shared<aidl::android::hardware::health::ChargerCallbackImpl>(binder));
+#endif
+    }
+    // ...
+}
+```
+
+#### SELinux rules for charger
+
+If your health AIDL service runs in a domain other than `hal_health_default`,
+add `charger_type` to it so the health HAL service can have charger-specific
+permissions. Example (assuming that your health AIDL service runs in domain
+`hal_health_tuna`:
+
+```text
+domain_trans(init, hal_health_tuna_exec, charger_vendor)
+```
diff --git a/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/BatteryCapacityLevel.aidl b/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/BatteryCapacityLevel.aidl
new file mode 100644
index 0000000..e543886
--- /dev/null
+++ b/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/BatteryCapacityLevel.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.health;
+@Backing(type="int") @VintfStability
+enum BatteryCapacityLevel {
+  UNSUPPORTED = -1,
+  UNKNOWN = 0,
+  CRITICAL = 1,
+  LOW = 2,
+  NORMAL = 3,
+  HIGH = 4,
+  FULL = 5,
+}
diff --git a/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/BatteryHealth.aidl b/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/BatteryHealth.aidl
new file mode 100644
index 0000000..4ce7952
--- /dev/null
+++ b/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/BatteryHealth.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.health;
+@Backing(type="int") @VintfStability
+enum BatteryHealth {
+  UNKNOWN = 1,
+  GOOD = 2,
+  OVERHEAT = 3,
+  DEAD = 4,
+  OVER_VOLTAGE = 5,
+  UNSPECIFIED_FAILURE = 6,
+  COLD = 7,
+}
diff --git a/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/BatteryStatus.aidl b/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/BatteryStatus.aidl
new file mode 100644
index 0000000..340b2ec
--- /dev/null
+++ b/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/BatteryStatus.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.health;
+@Backing(type="int") @VintfStability
+enum BatteryStatus {
+  UNKNOWN = 1,
+  CHARGING = 2,
+  DISCHARGING = 3,
+  NOT_CHARGING = 4,
+  FULL = 5,
+}
diff --git a/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/DiskStats.aidl b/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/DiskStats.aidl
new file mode 100644
index 0000000..5aa5890
--- /dev/null
+++ b/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/DiskStats.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.health;
+@VintfStability
+parcelable DiskStats {
+  long reads;
+  long readMerges;
+  long readSectors;
+  long readTicks;
+  long writes;
+  long writeMerges;
+  long writeSectors;
+  long writeTicks;
+  long ioInFlight;
+  long ioTicks;
+  long ioInQueue;
+}
diff --git a/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/HealthInfo.aidl b/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/HealthInfo.aidl
new file mode 100644
index 0000000..97d9e84
--- /dev/null
+++ b/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/HealthInfo.aidl
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.health;
+@VintfStability
+parcelable HealthInfo {
+  boolean chargerAcOnline;
+  boolean chargerUsbOnline;
+  boolean chargerWirelessOnline;
+  boolean chargerDockOnline;
+  int maxChargingCurrentMicroamps;
+  int maxChargingVoltageMicrovolts;
+  android.hardware.health.BatteryStatus batteryStatus;
+  android.hardware.health.BatteryHealth batteryHealth;
+  boolean batteryPresent;
+  int batteryLevel;
+  int batteryVoltageMillivolts;
+  int batteryTemperatureTenthsCelsius;
+  int batteryCurrentMicroamps;
+  int batteryCycleCount;
+  int batteryFullChargeUah;
+  int batteryChargeCounterUah;
+  String batteryTechnology;
+  int batteryCurrentAverageMicroamps;
+  android.hardware.health.DiskStats[] diskStats;
+  android.hardware.health.StorageInfo[] storageInfos;
+  android.hardware.health.BatteryCapacityLevel batteryCapacityLevel;
+  long batteryChargeTimeToFullNowSeconds;
+  int batteryFullChargeDesignCapacityUah;
+  const int BATTERY_CHARGE_TIME_TO_FULL_NOW_SECONDS_UNSUPPORTED = -1;
+}
diff --git a/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/IHealth.aidl b/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/IHealth.aidl
new file mode 100644
index 0000000..7016ae4
--- /dev/null
+++ b/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/IHealth.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.health;
+@VintfStability
+interface IHealth {
+  void registerCallback(in android.hardware.health.IHealthInfoCallback callback);
+  void unregisterCallback(in android.hardware.health.IHealthInfoCallback callback);
+  void update();
+  int getChargeCounterUah();
+  int getCurrentNowMicroamps();
+  int getCurrentAverageMicroamps();
+  int getCapacity();
+  long getEnergyCounterNwh();
+  android.hardware.health.BatteryStatus getChargeStatus();
+  android.hardware.health.StorageInfo[] getStorageInfo();
+  android.hardware.health.DiskStats[] getDiskStats();
+  android.hardware.health.HealthInfo getHealthInfo();
+  const int STATUS_UNKNOWN = 2;
+  const int STATUS_CALLBACK_DIED = 4;
+}
diff --git a/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/IHealthInfoCallback.aidl b/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/IHealthInfoCallback.aidl
new file mode 100644
index 0000000..1b6366f
--- /dev/null
+++ b/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/IHealthInfoCallback.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.health;
+@VintfStability
+interface IHealthInfoCallback {
+  oneway void healthInfoChanged(in android.hardware.health.HealthInfo info);
+}
diff --git a/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/StorageInfo.aidl b/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/StorageInfo.aidl
new file mode 100644
index 0000000..eaae5a6
--- /dev/null
+++ b/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/StorageInfo.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.health;
+@VintfStability
+parcelable StorageInfo {
+  int eol;
+  int lifetimeA;
+  int lifetimeB;
+  String version;
+}
diff --git a/health/aidl/android/hardware/health/BatteryCapacityLevel.aidl b/health/aidl/android/hardware/health/BatteryCapacityLevel.aidl
new file mode 100644
index 0000000..0c26fa2
--- /dev/null
+++ b/health/aidl/android/hardware/health/BatteryCapacityLevel.aidl
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.health;
+
+/**
+ * Battery capacity level. This enum provides additional information along side
+ * with the battery capacity.
+ * Clients of this HAL must use this value before inferring it from the
+ * battery capacity.
+ */
+@VintfStability
+@Backing(type="int")
+enum BatteryCapacityLevel {
+    /**
+     * Battery capacity level is unsupported.
+     * Battery capacity level must be set to this value if and only if the
+     * implementation is unsupported.
+     */
+    UNSUPPORTED = -1,
+    /**
+     * Battery capacity level is unknown.
+     * Battery capacity level must be set to this value if and only if battery
+     * is not present or the battery capacity level is unknown/uninitialized.
+     */
+    UNKNOWN,
+    /**
+     * Battery is at critical level. The Android framework must schedule a
+     * shutdown when it sees this value from the HAL.
+     */
+    CRITICAL,
+    /**
+     * Battery is low. The Android framework may limit the performance of
+     * the device when it sees this value from the HAL.
+     */
+    LOW,
+    /**
+     * Battery level is normal.
+     */
+    NORMAL,
+    /**
+     * Battery level is high.
+     */
+    HIGH,
+    /**
+     * Battery is full. It must be set to FULL if and only if battery level is
+     * 100.
+     */
+    FULL,
+}
diff --git a/health/aidl/android/hardware/health/BatteryHealth.aidl b/health/aidl/android/hardware/health/BatteryHealth.aidl
new file mode 100644
index 0000000..2b6e51f
--- /dev/null
+++ b/health/aidl/android/hardware/health/BatteryHealth.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.health;
+
+/**
+ * Possible values for Battery Health.
+ * Note: These are currently in sync with BatteryManager and must not
+ * be extended / altered.
+ */
+@VintfStability
+@Backing(type="int")
+enum BatteryHealth {
+    UNKNOWN = 1,
+    GOOD = 2,
+    OVERHEAT = 3,
+    DEAD = 4,
+    OVER_VOLTAGE = 5,
+    /**
+     * Battery experienced an unknown/unspecified failure.
+     */
+    UNSPECIFIED_FAILURE = 6,
+    COLD = 7,
+}
diff --git a/health/aidl/android/hardware/health/BatteryStatus.aidl b/health/aidl/android/hardware/health/BatteryStatus.aidl
new file mode 100644
index 0000000..774b28e
--- /dev/null
+++ b/health/aidl/android/hardware/health/BatteryStatus.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.health;
+
+/**
+ * Possible values for Battery Status.
+ * Note: These are currently in sync with BatteryManager and must not
+ * be extended / altered.
+ */
+@VintfStability
+@Backing(type="int")
+enum BatteryStatus {
+    UNKNOWN = 1,
+    CHARGING = 2,
+    DISCHARGING = 3,
+    /**
+     * Battery is *not* charging - special case when charger is present
+     * but battery isn't charging
+     */
+    NOT_CHARGING = 4,
+    FULL = 5,
+}
diff --git a/health/aidl/android/hardware/health/DiskStats.aidl b/health/aidl/android/hardware/health/DiskStats.aidl
new file mode 100644
index 0000000..532cbfd
--- /dev/null
+++ b/health/aidl/android/hardware/health/DiskStats.aidl
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.health;
+
+/*
+ * Disk statistics since boot.
+ *
+ * See {@code struct disk_stats} in {@code storaged} for interpretations of these fields.
+ *
+ * All integers in this struct must be interpreted as unsigned.
+ */
+@VintfStability
+parcelable DiskStats {
+    /**
+     * Number of reads processed.
+     *
+     * Value must be interpreted as unsigned.
+     */
+    long reads;
+    /**
+     * number of read I/Os merged with in-queue I/Os.
+     *
+     * Value must be interpreted as unsigned.
+     */
+    long readMerges;
+    /**
+     * number of sectors read.
+     *
+     * Value must be interpreted as unsigned.
+     */
+    long readSectors;
+    /**
+     * total wait time for read requests.
+     *
+     * Value must be interpreted as unsigned.
+     */
+    long readTicks;
+    /**
+     * number of writes processed.
+     *
+     * Value must be interpreted as unsigned.
+     */
+    long writes;
+    /**
+     * number of writes merged with in-queue I/Os.
+     *
+     * Value must be interpreted as unsigned.
+     */
+    long writeMerges;
+    /**
+     * number of sectors written.
+     *
+     * Value must be interpreted as unsigned.
+     */
+    long writeSectors;
+    /**
+     * total wait time for write requests.
+     *
+     * Value must be interpreted as unsigned.
+     */
+    long writeTicks;
+    /**
+     * number of I/Os currently in flight.
+     *
+     * Value must be interpreted as unsigned.
+     */
+    long ioInFlight;
+    /**
+     * total time this block device has been active.
+     *
+     * Value must be interpreted as unsigned.
+     */
+    long ioTicks;
+    /**
+     * total wait time for all requests.
+     *
+     * Value must be interpreted as unsigned.
+     */
+    long ioInQueue;
+}
diff --git a/health/aidl/android/hardware/health/HealthInfo.aidl b/health/aidl/android/hardware/health/HealthInfo.aidl
new file mode 100644
index 0000000..5b98baf
--- /dev/null
+++ b/health/aidl/android/hardware/health/HealthInfo.aidl
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.health;
+
+import android.hardware.health.BatteryCapacityLevel;
+import android.hardware.health.BatteryHealth;
+import android.hardware.health.BatteryStatus;
+import android.hardware.health.DiskStats;
+import android.hardware.health.StorageInfo;
+
+/**
+ * Health Information.
+ */
+@VintfStability
+parcelable HealthInfo {
+    /**
+     * AC charger state - 'true' if online
+     */
+    boolean chargerAcOnline;
+    /**
+     * USB charger state - 'true' if online
+     */
+    boolean chargerUsbOnline;
+    /**
+     * Wireless charger state - 'true' if online
+     */
+    boolean chargerWirelessOnline;
+    /**
+     * Dock charger state - 'true' if online
+     */
+    boolean chargerDockOnline;
+    /**
+     * Maximum charging current supported by charger in µA
+     */
+    int maxChargingCurrentMicroamps;
+    /**
+     * Maximum charging voltage supported by charger in µV
+     */
+    int maxChargingVoltageMicrovolts;
+
+    android.hardware.health.BatteryStatus batteryStatus;
+
+    android.hardware.health.BatteryHealth batteryHealth;
+    /**
+     * 'true' if battery is present
+     */
+    boolean batteryPresent;
+    /**
+     * Remaining battery capacity in percent
+     */
+    int batteryLevel;
+    /**
+     * Instantaneous battery voltage in millivolts (mV).
+     *
+     * Historically, the unit of this field is microvolts (µV), but all
+     * clients and implementations uses millivolts in practice, making it
+     * the de-facto standard.
+     */
+    int batteryVoltageMillivolts;
+    /**
+     * Instantaneous battery temperature in tenths of degrees Celsius
+     */
+    int batteryTemperatureTenthsCelsius;
+    /**
+     * Instantaneous battery current in µA
+     */
+    int batteryCurrentMicroamps;
+    /**
+     * Battery charge cycle count
+     */
+    int batteryCycleCount;
+    /**
+     * Battery charge value when it is considered to be "full" in µA-h
+     */
+    int batteryFullChargeUah;
+    /**
+     * Instantaneous battery capacity in µA-h
+     */
+    int batteryChargeCounterUah;
+    /**
+     * Battery technology, e.g. "Li-ion, Li-Poly" etc.
+     */
+    String batteryTechnology;
+    /**
+     * Average battery current in µA. Will be 0 if unsupported.
+     */
+    int batteryCurrentAverageMicroamps;
+    /**
+     * Disk Statistics. Will be an empty vector if unsupported.
+     */
+    DiskStats[] diskStats;
+    /**
+     * Information on storage devices. Will be an empty vector if
+     * unsupported.
+     */
+    StorageInfo[] storageInfos;
+    /**
+     * Battery capacity level. See {@link BatteryCapacityLevel} for more details.
+     */
+    BatteryCapacityLevel batteryCapacityLevel;
+
+    /**
+     * Value of {@link #batteryChargeTimeToFullNowSeconds} if it is not
+     * supported.
+     */
+    const int BATTERY_CHARGE_TIME_TO_FULL_NOW_SECONDS_UNSUPPORTED = -1;
+    /**
+     * Estimated time to fully charge the device (in seconds).
+     * Value must be BATTERY_CHARGE_TIME_TO_FULL_NOW_SECONDS_UNSUPPORTED if and
+     * only if the implementation is unsupported.
+     * Value must be 0 if and only if batteryCapacityLevel is FULL or UNKNOWN.
+     * Otherwise, value must be positive.
+     */
+    long batteryChargeTimeToFullNowSeconds;
+    /**
+     * Estimated battery full charge design capacity (in microamp hours, µAh).
+     * Value must be 0 if unknown.
+     * Value must be greater than 100 000 µAh if known.
+     * Value must be less than 100 000 000 µAh if known.
+     */
+    int batteryFullChargeDesignCapacityUah;
+}
diff --git a/health/aidl/android/hardware/health/IHealth.aidl b/health/aidl/android/hardware/health/IHealth.aidl
new file mode 100644
index 0000000..d541eca
--- /dev/null
+++ b/health/aidl/android/hardware/health/IHealth.aidl
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.health;
+
+import android.hardware.health.BatteryStatus;
+import android.hardware.health.DiskStats;
+import android.hardware.health.HealthInfo;
+import android.hardware.health.IHealthInfoCallback;
+import android.hardware.health.StorageInfo;
+
+/**
+ * IHealth manages health info and posts events on registered callbacks.
+ *
+ * Implementations must send health info to all callbacks periodically.
+ */
+@VintfStability
+interface IHealth {
+    /** Status code for function. The operation encounters an unknown error. */
+    const int STATUS_UNKNOWN = 2;
+
+    /**
+     * Status code for function.
+     * A registered callback object is dead.
+     */
+    const int STATUS_CALLBACK_DIED = 4;
+
+    /**
+     * Register a callback for any health info events.
+     *
+     * Registering a new callback must not unregister the old one; the old
+     * callback remains registered until one of the following happens:
+     * - A client explicitly calls {@link #unregisterCallback} to unregister it.
+     * - The client process that hosts the callback dies.
+     *
+     * @param callback the callback to register.
+     * @return If error, return service specific error with code STATUS_UNKNOWN.
+     */
+    void registerCallback(in IHealthInfoCallback callback);
+
+    /**
+     * Explicitly unregister a callback that is previously registered through
+     * {@link #registerCallback}.
+     *
+     * @param callback the callback to unregister.
+     * @return If error:
+     *         - Return exception with code EX_ILLEGAL_ARGUMENT
+     *           if callback is not registered previously,
+     *         - Return service specific error with code STATUS_UNKNOWN
+     *           for other errors.
+     */
+    void unregisterCallback(in IHealthInfoCallback callback);
+
+    /**
+     * Schedule update.
+     *
+     * When update() is called, the service must notify all registered callbacks
+     * with the most recent health info.
+     *
+     * @return If error, return service specific error with code:
+     *         - STATUS_CALLBACK_DIED if any registered callback is dead,
+     *         - STATUS_UNKNOWN for other errors.
+     */
+    void update();
+
+    /**
+     * Get battery capacity in microampere-hours(µAh).
+     *
+     * @return battery capacity if successful.
+     *         If error:
+     *         - Return exception with code EX_UNSUPPORTED_OPERATION
+     *           if this property is not supported
+     *           (e.g. the file that stores this property does not exist),
+     *         - Retrurn service specific error with code
+     *           STATUS_UNKNOWN for other errors.
+     */
+    int getChargeCounterUah();
+
+    /**
+     * Get instantaneous battery current in microamperes(µA).
+     *
+     * Positive values indicate net current entering the battery from a charge
+     * source, negative values indicate net current discharging from the
+     * battery.
+     *
+     * @return instantaneous battery current if successful.
+     *         If error:
+     *         - Return exception with code EX_UNSUPPORTED_OPERATION
+     *           if this property is not supported
+     *                 (e.g. the file that stores this property does not exist),
+     *         - Return service specific error with code STATUS_UNKNOWN
+     *           for for other errors.
+     */
+    int getCurrentNowMicroamps();
+
+    /**
+     * Get average battery current in microamperes(µA).
+     *
+     * Positive values indicate net current entering the battery from a charge
+     * source, negative values indicate net current discharging from the
+     * battery. The time period over which the average is computed may depend on
+     * the fuel gauge hardware and its configuration.
+     *
+     * @return average battery current if successful.
+     *         If error:
+     *         - Return exception with code EX_UNSUPPORTED_OPERATION
+     *           if this property is not supported
+     *                 (e.g. the file that stores this property does not exist),
+     *         - Return service specific error with code STATUS_UNKNOWN
+     *           for for other errors.
+     */
+    int getCurrentAverageMicroamps();
+
+    /**
+     * Get remaining battery capacity percentage of total capacity
+     * (with no fractional part).
+     *
+     * @return remaining battery capacity if successful.
+     *         If error:
+     *         - Return exception with code EX_UNSUPPORTED_OPERATION
+     *           if this property is not supported
+     *                 (e.g. the file that stores this property does not exist),
+     *         - Return service specific error with code STATUS_UNKNOWN
+     *           for for other errors.
+     */
+    int getCapacity();
+
+    /**
+     * Get battery remaining energy in nanowatt-hours.
+     *
+     * @return remaining energy if successful.
+     *         If error:
+     *         - Return exception with code EX_UNSUPPORTED_OPERATION
+     *           if this property is not supported,
+     *         - Return service specific error with code STATUS_UNKNOWN
+     *           for for other errors.
+     */
+    long getEnergyCounterNwh();
+
+    /**
+     * Get battery charge status.
+     *
+     * @return charge status if successful.
+     *         If error:
+     *         - Return exception with code EX_UNSUPPORTED_OPERATION
+     *           if this property is not supported
+     *                 (e.g. the file that stores this property does not exist),
+     *         - Return service specific error with code STATUS_UNKNOWN
+     *           for other errors.
+     */
+    BatteryStatus getChargeStatus();
+
+    /**
+     * Get storage info.
+     *
+     * @return vector of StorageInfo structs if successful.
+     *         If error:
+     *         - Return exception with code EX_UNSUPPORTED_OPERATION
+     *           if this property is not supported,
+     *         - Return service specific error with code STATUS_UNKNOWN
+     *           for other errors.
+     */
+    StorageInfo[] getStorageInfo();
+
+    /**
+     * Gets disk statistics (number of reads/writes processed, number of I/O
+     * operations in flight etc).
+     *
+     * @return vector of disk statistics if successful.
+     *         The mapping is index 0->sda, 1->sdb and so on.
+     *         If error:
+     *         - Return exception with code EX_UNSUPPORTED_OPERATION
+     *           if this property is not supported,
+     *         - Return service specific error with code STATUS_UNKNOWN
+     *           for other errors.
+     */
+    DiskStats[] getDiskStats();
+
+    /**
+     * Get Health Information.
+     *
+     * @return Health information if successful.
+     *         If error:
+     *         - Return exception with code EX_UNSUPPORTED_OPERATION
+     *           if this API is not supported,
+     *         - Return service specific error with code STATUS_UNKNOWN
+     *           for for other errors.
+     */
+    HealthInfo getHealthInfo();
+}
diff --git a/health/aidl/android/hardware/health/IHealthInfoCallback.aidl b/health/aidl/android/hardware/health/IHealthInfoCallback.aidl
new file mode 100644
index 0000000..e9720fa
--- /dev/null
+++ b/health/aidl/android/hardware/health/IHealthInfoCallback.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.health;
+
+import android.hardware.health.HealthInfo;
+
+/**
+ * IHealthInfoCallback is the updated callback interface to
+ * {@link IHealth#registerCallback}.
+ */
+@VintfStability
+interface IHealthInfoCallback {
+    /**
+     * An implementation of IHealth must call healthInfoChanged on all
+     * registered callbacks after health info changes.
+     * @param info the updated HealthInfo
+     */
+    oneway void healthInfoChanged(in HealthInfo info);
+}
diff --git a/health/aidl/android/hardware/health/StorageInfo.aidl b/health/aidl/android/hardware/health/StorageInfo.aidl
new file mode 100644
index 0000000..4c4dace
--- /dev/null
+++ b/health/aidl/android/hardware/health/StorageInfo.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.health;
+
+/*
+ * Information on storage device including life time estimates, end of life
+ * information and other attributes.
+ *
+ * All integers in this struct must be interpreted as non-negative.
+ */
+@VintfStability
+parcelable StorageInfo {
+    /**
+     * pre-eol (end of life) information. Follows JEDEC standard No.84-B50.
+     *
+     * Value must be interpreted as non-negative.
+     */
+    int eol;
+    /**
+     * device life time estimation (type A). Follows JEDEC standard No.84-B50.
+     *
+     * Value must be interpreted as non-negative.
+     */
+    int lifetimeA;
+    /**
+     * device life time estimation (type B). Follows JEDEC standard No.84-B50.
+     *
+     * Value must be interpreted as non-negative.
+     */
+    int lifetimeB;
+    /**
+     * version string
+     */
+    String version;
+}
diff --git a/health/aidl/android/hardware/health/Translate.java b/health/aidl/android/hardware/health/Translate.java
new file mode 100644
index 0000000..4f840b8
--- /dev/null
+++ b/health/aidl/android/hardware/health/Translate.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.health;
+
+public class Translate {
+    static public android.hardware.health.StorageInfo h2aTranslate(
+            android.hardware.health.V2_0.StorageInfo in) {
+        android.hardware.health.StorageInfo out = new android.hardware.health.StorageInfo();
+        out.eol = in.eol;
+        out.lifetimeA = in.lifetimeA;
+        out.lifetimeB = in.lifetimeB;
+        out.version = in.version;
+        return out;
+    }
+
+    static public android.hardware.health.DiskStats h2aTranslate(
+            android.hardware.health.V2_0.DiskStats in) {
+        android.hardware.health.DiskStats out = new android.hardware.health.DiskStats();
+        out.reads = in.reads;
+        out.readMerges = in.readMerges;
+        out.readSectors = in.readSectors;
+        out.readTicks = in.readTicks;
+        out.writes = in.writes;
+        out.writeMerges = in.writeMerges;
+        out.writeSectors = in.writeSectors;
+        out.writeTicks = in.writeTicks;
+        out.ioInFlight = in.ioInFlight;
+        out.ioTicks = in.ioTicks;
+        out.ioInQueue = in.ioInQueue;
+        return out;
+    }
+
+    private static void h2aTranslateInternal(
+            android.hardware.health.HealthInfo out, android.hardware.health.V1_0.HealthInfo in) {
+        out.chargerAcOnline = in.chargerAcOnline;
+        out.chargerUsbOnline = in.chargerUsbOnline;
+        out.chargerWirelessOnline = in.chargerWirelessOnline;
+        out.maxChargingCurrentMicroamps = in.maxChargingCurrent;
+        out.maxChargingVoltageMicrovolts = in.maxChargingVoltage;
+        out.batteryStatus = in.batteryStatus;
+        out.batteryHealth = in.batteryHealth;
+        out.batteryPresent = in.batteryPresent;
+        out.batteryLevel = in.batteryLevel;
+        out.batteryVoltageMillivolts = in.batteryVoltage;
+        out.batteryTemperatureTenthsCelsius = in.batteryTemperature;
+        out.batteryCurrentMicroamps = in.batteryCurrent;
+        out.batteryCycleCount = in.batteryCycleCount;
+        out.batteryFullChargeUah = in.batteryFullCharge;
+        out.batteryChargeCounterUah = in.batteryChargeCounter;
+        out.batteryTechnology = in.batteryTechnology;
+    }
+
+    public static android.hardware.health.HealthInfo h2aTranslate(
+            android.hardware.health.V1_0.HealthInfo in) {
+        android.hardware.health.HealthInfo out = new android.hardware.health.HealthInfo();
+        h2aTranslateInternal(out, in);
+        return out;
+    }
+
+    static public android.hardware.health.HealthInfo h2aTranslate(
+            android.hardware.health.V2_1.HealthInfo in) {
+        android.hardware.health.HealthInfo out = new android.hardware.health.HealthInfo();
+        h2aTranslateInternal(out, in.legacy.legacy);
+        out.batteryCurrentAverageMicroamps = in.legacy.batteryCurrentAverage;
+        out.diskStats = new android.hardware.health.DiskStats[in.legacy.diskStats.size()];
+        for (int i = 0; i < in.legacy.diskStats.size(); i++) {
+            out.diskStats[i] = h2aTranslate(in.legacy.diskStats.get(i));
+        }
+        out.storageInfos = new android.hardware.health.StorageInfo[in.legacy.storageInfos.size()];
+        for (int i = 0; i < in.legacy.storageInfos.size(); i++) {
+            out.storageInfos[i] = h2aTranslate(in.legacy.storageInfos.get(i));
+        }
+        out.batteryCapacityLevel = in.batteryCapacityLevel;
+        out.batteryChargeTimeToFullNowSeconds = in.batteryChargeTimeToFullNowSeconds;
+        out.batteryFullChargeDesignCapacityUah = in.batteryFullChargeDesignCapacityUah;
+        return out;
+    }
+}
diff --git a/health/aidl/android/hardware/health/translate-ndk.cpp b/health/aidl/android/hardware/health/translate-ndk.cpp
new file mode 100644
index 0000000..78880cc
--- /dev/null
+++ b/health/aidl/android/hardware/health/translate-ndk.cpp
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "android/hardware/health/translate-ndk.h"
+
+namespace android::h2a {
+
+static_assert(aidl::android::hardware::health::BatteryStatus::UNKNOWN ==
+              static_cast<aidl::android::hardware::health::BatteryStatus>(
+                      ::android::hardware::health::V1_0::BatteryStatus::UNKNOWN));
+static_assert(aidl::android::hardware::health::BatteryStatus::CHARGING ==
+              static_cast<aidl::android::hardware::health::BatteryStatus>(
+                      ::android::hardware::health::V1_0::BatteryStatus::CHARGING));
+static_assert(aidl::android::hardware::health::BatteryStatus::DISCHARGING ==
+              static_cast<aidl::android::hardware::health::BatteryStatus>(
+                      ::android::hardware::health::V1_0::BatteryStatus::DISCHARGING));
+static_assert(aidl::android::hardware::health::BatteryStatus::NOT_CHARGING ==
+              static_cast<aidl::android::hardware::health::BatteryStatus>(
+                      ::android::hardware::health::V1_0::BatteryStatus::NOT_CHARGING));
+static_assert(aidl::android::hardware::health::BatteryStatus::FULL ==
+              static_cast<aidl::android::hardware::health::BatteryStatus>(
+                      ::android::hardware::health::V1_0::BatteryStatus::FULL));
+
+static_assert(aidl::android::hardware::health::BatteryHealth::UNKNOWN ==
+              static_cast<aidl::android::hardware::health::BatteryHealth>(
+                      ::android::hardware::health::V1_0::BatteryHealth::UNKNOWN));
+static_assert(aidl::android::hardware::health::BatteryHealth::GOOD ==
+              static_cast<aidl::android::hardware::health::BatteryHealth>(
+                      ::android::hardware::health::V1_0::BatteryHealth::GOOD));
+static_assert(aidl::android::hardware::health::BatteryHealth::OVERHEAT ==
+              static_cast<aidl::android::hardware::health::BatteryHealth>(
+                      ::android::hardware::health::V1_0::BatteryHealth::OVERHEAT));
+static_assert(aidl::android::hardware::health::BatteryHealth::DEAD ==
+              static_cast<aidl::android::hardware::health::BatteryHealth>(
+                      ::android::hardware::health::V1_0::BatteryHealth::DEAD));
+static_assert(aidl::android::hardware::health::BatteryHealth::OVER_VOLTAGE ==
+              static_cast<aidl::android::hardware::health::BatteryHealth>(
+                      ::android::hardware::health::V1_0::BatteryHealth::OVER_VOLTAGE));
+static_assert(aidl::android::hardware::health::BatteryHealth::UNSPECIFIED_FAILURE ==
+              static_cast<aidl::android::hardware::health::BatteryHealth>(
+                      ::android::hardware::health::V1_0::BatteryHealth::UNSPECIFIED_FAILURE));
+static_assert(aidl::android::hardware::health::BatteryHealth::COLD ==
+              static_cast<aidl::android::hardware::health::BatteryHealth>(
+                      ::android::hardware::health::V1_0::BatteryHealth::COLD));
+
+static_assert(aidl::android::hardware::health::BatteryCapacityLevel::UNSUPPORTED ==
+              static_cast<aidl::android::hardware::health::BatteryCapacityLevel>(
+                      ::android::hardware::health::V2_1::BatteryCapacityLevel::UNSUPPORTED));
+static_assert(aidl::android::hardware::health::BatteryCapacityLevel::UNKNOWN ==
+              static_cast<aidl::android::hardware::health::BatteryCapacityLevel>(
+                      ::android::hardware::health::V2_1::BatteryCapacityLevel::UNKNOWN));
+static_assert(aidl::android::hardware::health::BatteryCapacityLevel::CRITICAL ==
+              static_cast<aidl::android::hardware::health::BatteryCapacityLevel>(
+                      ::android::hardware::health::V2_1::BatteryCapacityLevel::CRITICAL));
+static_assert(aidl::android::hardware::health::BatteryCapacityLevel::LOW ==
+              static_cast<aidl::android::hardware::health::BatteryCapacityLevel>(
+                      ::android::hardware::health::V2_1::BatteryCapacityLevel::LOW));
+static_assert(aidl::android::hardware::health::BatteryCapacityLevel::NORMAL ==
+              static_cast<aidl::android::hardware::health::BatteryCapacityLevel>(
+                      ::android::hardware::health::V2_1::BatteryCapacityLevel::NORMAL));
+static_assert(aidl::android::hardware::health::BatteryCapacityLevel::HIGH ==
+              static_cast<aidl::android::hardware::health::BatteryCapacityLevel>(
+                      ::android::hardware::health::V2_1::BatteryCapacityLevel::HIGH));
+static_assert(aidl::android::hardware::health::BatteryCapacityLevel::FULL ==
+              static_cast<aidl::android::hardware::health::BatteryCapacityLevel>(
+                      ::android::hardware::health::V2_1::BatteryCapacityLevel::FULL));
+
+__attribute__((warn_unused_result)) bool translate(
+        const ::android::hardware::health::V2_0::StorageInfo& in,
+        aidl::android::hardware::health::StorageInfo* out) {
+    out->eol = in.eol;
+    out->lifetimeA = in.lifetimeA;
+    out->lifetimeB = in.lifetimeB;
+    out->version = in.version;
+    return true;
+}
+
+__attribute__((warn_unused_result)) bool translate(
+        const ::android::hardware::health::V2_0::DiskStats& in,
+        aidl::android::hardware::health::DiskStats* out) {
+    out->reads = static_cast<int64_t>(in.reads);
+    out->readMerges = static_cast<int64_t>(in.readMerges);
+    out->readSectors = static_cast<int64_t>(in.readSectors);
+    out->readTicks = static_cast<int64_t>(in.readTicks);
+    out->writes = static_cast<int64_t>(in.writes);
+    out->writeMerges = static_cast<int64_t>(in.writeMerges);
+    out->writeSectors = static_cast<int64_t>(in.writeSectors);
+    out->writeTicks = static_cast<int64_t>(in.writeTicks);
+    out->ioInFlight = static_cast<int64_t>(in.ioInFlight);
+    out->ioTicks = static_cast<int64_t>(in.ioTicks);
+    out->ioInQueue = static_cast<int64_t>(in.ioInQueue);
+    return true;
+}
+
+__attribute__((warn_unused_result)) bool translate(
+        const ::android::hardware::health::V2_0::HealthInfo& in,
+        aidl::android::hardware::health::HealthInfo* out) {
+    out->chargerAcOnline = static_cast<bool>(in.legacy.chargerAcOnline);
+    out->chargerUsbOnline = static_cast<bool>(in.legacy.chargerUsbOnline);
+    out->chargerWirelessOnline = static_cast<bool>(in.legacy.chargerWirelessOnline);
+    out->maxChargingCurrentMicroamps = static_cast<int32_t>(in.legacy.maxChargingCurrent);
+    out->maxChargingVoltageMicrovolts = static_cast<int32_t>(in.legacy.maxChargingVoltage);
+    out->batteryStatus =
+            static_cast<aidl::android::hardware::health::BatteryStatus>(in.legacy.batteryStatus);
+    out->batteryHealth =
+            static_cast<aidl::android::hardware::health::BatteryHealth>(in.legacy.batteryHealth);
+    out->batteryPresent = static_cast<bool>(in.legacy.batteryPresent);
+    out->batteryLevel = static_cast<int32_t>(in.legacy.batteryLevel);
+    out->batteryVoltageMillivolts = static_cast<int32_t>(in.legacy.batteryVoltage);
+    out->batteryTemperatureTenthsCelsius = static_cast<int32_t>(in.legacy.batteryTemperature);
+    out->batteryCurrentMicroamps = static_cast<int32_t>(in.legacy.batteryCurrent);
+    out->batteryCycleCount = static_cast<int32_t>(in.legacy.batteryCycleCount);
+    out->batteryFullChargeUah = static_cast<int32_t>(in.legacy.batteryFullCharge);
+    out->batteryChargeCounterUah = static_cast<int32_t>(in.legacy.batteryChargeCounter);
+    out->batteryTechnology = in.legacy.batteryTechnology;
+    out->batteryCurrentAverageMicroamps = static_cast<int32_t>(in.batteryCurrentAverage);
+    out->diskStats.clear();
+    out->diskStats.resize(in.diskStats.size());
+    for (size_t i = 0; i < in.diskStats.size(); ++i)
+        if (!translate(in.diskStats[i], &out->diskStats[i])) return false;
+    out->storageInfos.clear();
+    out->storageInfos.resize(in.storageInfos.size());
+    for (size_t i = 0; i < in.storageInfos.size(); ++i)
+        if (!translate(in.storageInfos[i], &out->storageInfos[i])) return false;
+    return true;
+}
+__attribute__((warn_unused_result)) bool translate(
+        const ::android::hardware::health::V2_1::HealthInfo& in,
+        aidl::android::hardware::health::HealthInfo* out) {
+    if (!translate(in.legacy, out)) return false;
+    out->batteryCapacityLevel = static_cast<aidl::android::hardware::health::BatteryCapacityLevel>(
+            in.batteryCapacityLevel);
+    out->batteryChargeTimeToFullNowSeconds =
+            static_cast<int64_t>(in.batteryChargeTimeToFullNowSeconds);
+    out->batteryFullChargeDesignCapacityUah =
+            static_cast<int32_t>(in.batteryFullChargeDesignCapacityUah);
+    return true;
+}
+
+}  // namespace android::h2a
diff --git a/health/aidl/default/Android.bp b/health/aidl/default/Android.bp
new file mode 100644
index 0000000..0d426da
--- /dev/null
+++ b/health/aidl/default/Android.bp
@@ -0,0 +1,228 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+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: "libhealth_aidl_common_defaults",
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "libcutils",
+        "liblog",
+        "libutils",
+        "android.hardware.health-V1-ndk",
+
+        // TODO(b/177269435): remove when BatteryMonitor works with AIDL HealthInfo.
+        "libhidlbase",
+    ],
+    static_libs: [
+        "libbatterymonitor",
+        "libhealthloop",
+
+        // TODO(b/177269435): remove when BatteryMonitor works with AIDL HealthInfo.
+        "android.hardware.health-translate-ndk",
+    ],
+}
+
+// Dependency to libhealthd_charger_ui. No UI in recovery.
+cc_defaults {
+    name: "libhealth_aidl_charger_defaults",
+    shared_libs: [
+        // common
+        "android.hardware.health-V1-ndk",
+        "libbase",
+        "libcutils",
+        "liblog",
+        "libutils",
+
+        // charger UI only
+        "libpng",
+    ],
+
+    static_libs: [
+        // common
+        "libbatterymonitor",
+        "libhealthloop",
+
+        // charger UI only
+        "libhealthd_draw",
+        "libhealthd_charger_ui",
+        "libminui",
+        "libsuspend",
+    ],
+
+    target: {
+        recovery: {
+            // No UI and libsuspend for recovery charger.
+            cflags: [
+                "-DCHARGER_FORCE_NO_UI=1",
+            ],
+            exclude_shared_libs: [
+                "libpng",
+            ],
+            exclude_static_libs: [
+                "libhealthd_draw",
+                "libhealthd_charger_ui",
+                "libminui",
+                "libsuspend",
+            ],
+        },
+    },
+}
+
+// AIDL version of libhealth2impl.
+// A helper library for health HAL implementation.
+// HAL implementations can link to this library and extend the Health class.
+cc_library_static {
+    name: "libhealth_aidl_impl",
+    defaults: [
+        "libhealth_aidl_common_defaults",
+        "libhealth_aidl_charger_defaults",
+    ],
+    vendor: true,
+    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",
+            ],
+        },
+    },
+}
+
+// Users of libhealth_aidl_impl should use this defaults.
+cc_defaults {
+    name: "libhealth_aidl_impl_user",
+    defaults: [
+        "libhealth_aidl_common_defaults",
+        "libhealth_aidl_charger_defaults",
+    ],
+}
+
+// AIDL version of android.hardware.health@2.1-service.
+// Default binder service of the health HAL.
+cc_defaults {
+    name: "android.hardware.health-service.example-defaults",
+    relative_install_path: "hw",
+    vintf_fragments: ["android.hardware.health-service.example.xml"],
+    defaults: [
+        "libhealth_aidl_impl_user",
+    ],
+    static_libs: [
+        "libhealth_aidl_impl",
+    ],
+    srcs: ["main.cpp"],
+}
+
+cc_binary {
+    name: "android.hardware.health-service.example",
+    vendor: true,
+    defaults: ["android.hardware.health-service.example-defaults"],
+    init_rc: ["android.hardware.health-service.example.rc"],
+    overrides: ["charger"],
+}
+
+cc_binary {
+    name: "android.hardware.health-service.example_recovery",
+    recovery: true,
+    defaults: ["android.hardware.health-service.example-defaults"],
+    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",
+    ],
+    static_libs: [
+        "android.hardware.health-V1-ndk",
+        "libbase",
+        "libbinder_random_parcel",
+        "libcutils",
+        "liblog",
+        "libutils",
+        "fuzz_libhealth_aidl_impl",
+    ],
+    target: {
+        android: {
+            shared_libs: [
+                "libbinder_ndk",
+                "libbinder",
+            ],
+        },
+        host: {
+            static_libs: [
+                "libbinder_ndk",
+                "libbinder",
+            ],
+        },
+        darwin: {
+            enabled: false,
+        },
+    },
+    srcs: ["fuzzer.cpp"],
+    fuzz_config: {
+        cc: [
+            "hamzeh@google.com",
+        ],
+    },
+}
diff --git a/health/aidl/default/ChargerUtils.cpp b/health/aidl/default/ChargerUtils.cpp
new file mode 100644
index 0000000..f8e208b
--- /dev/null
+++ b/health/aidl/default/ChargerUtils.cpp
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <health-impl/ChargerUtils.h>
+
+namespace aidl::android::hardware::health::charger {
+
+std::optional<bool> ChargerCallback::ChargerShouldKeepScreenOn() {
+    return service_->ShouldKeepScreenOn();
+}
+
+bool ChargerCallback::ChargerIsOnline() {
+    auto hal_health_loop_sp = hal_health_loop_.lock();
+    if (hal_health_loop_sp == nullptr) {
+        // Assume no charger
+        return false;
+    }
+    return hal_health_loop_sp->charger_online();
+}
+
+void ChargerCallback::ChargerInitConfig(healthd_config* config) {
+    auto hal_health_loop_sp = hal_health_loop_.lock();
+    if (hal_health_loop_sp == nullptr) {
+        return;
+    }
+    return service_->OnInit(hal_health_loop_sp.get(), config);
+}
+
+int ChargerCallback::ChargerRegisterEvent(int fd, BoundFunction func, EventWakeup wakeup) {
+    auto hal_health_loop_sp = hal_health_loop_.lock();
+    if (hal_health_loop_sp == nullptr) {
+        return -1;
+    }
+    return hal_health_loop_sp->RegisterEvent(fd, func, wakeup);
+}
+
+void ChargerCallback::set_hal_health_loop(const std::weak_ptr<HalHealthLoop>& hal_health_loop) {
+    hal_health_loop_ = std::move(hal_health_loop);
+}
+
+// Implements HalHealthLoopCallback for AIDL charger
+// Adapter of (Charger, Health) ->  HalHealthLoopCallback
+class LoopCallback : public HalHealthLoopCallback {
+  public:
+    LoopCallback(const std::shared_ptr<Health>& service, ChargerCallback* charger_callback)
+        : service_(service), charger_(std::make_unique<::android::Charger>(charger_callback)) {}
+
+    void OnHeartbeat() override {
+        service_->OnHeartbeat();
+        charger_->OnHeartbeat();
+    }
+    // Return the minimum timeout. Negative values are treated as no values.
+    int OnPrepareToWait() override {
+        int timeout1 = service_->OnPrepareToWait();
+        int timeout2 = charger_->OnPrepareToWait();
+
+        if (timeout1 < 0) return timeout2;
+        if (timeout2 < 0) return timeout1;
+        return std::min(timeout1, timeout2);
+    }
+
+    void OnInit(HalHealthLoop*, struct healthd_config* config) override {
+        // Charger::OnInit calls ChargerInitConfig, which calls into the real Health::OnInit.
+        charger_->OnInit(config);
+    }
+
+    void OnHealthInfoChanged(const HealthInfo& health_info) override {
+        charger_->OnHealthInfoChanged(::android::ChargerHealthInfo{
+                .battery_level = health_info.batteryLevel,
+                .battery_status = health_info.batteryStatus,
+        });
+        service_->OnHealthInfoChanged(health_info);
+    }
+
+  private:
+    std::shared_ptr<Health> service_;
+    std::unique_ptr<::android::Charger> charger_;
+};
+
+int ChargerModeMain(const std::shared_ptr<Health>& binder,
+                    const std::shared_ptr<ChargerCallback>& charger_callback) {
+    LOG(INFO) << "Starting charger mode.";
+    //   parent stack ==========================================
+    //   current stack                                         ||
+    //    ||                                                   ||
+    //    V                                                    V
+    // hal_health_loop => loop_callback => charger --(raw)--> charger_callback
+    //    ^----------------(weak)---------------------------------'
+    auto loop_callback = std::make_shared<LoopCallback>(binder, charger_callback.get());
+    auto hal_health_loop = std::make_shared<HalHealthLoop>(binder, std::move(loop_callback));
+    charger_callback->set_hal_health_loop(hal_health_loop);
+    return hal_health_loop->StartLoop();
+}
+
+}  // namespace aidl::android::hardware::health::charger
diff --git a/health/aidl/default/HalHealthLoop.cpp b/health/aidl/default/HalHealthLoop.cpp
new file mode 100644
index 0000000..ec23c10
--- /dev/null
+++ b/health/aidl/default/HalHealthLoop.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <health-impl/HalHealthLoop.h>
+
+#include <android-base/logging.h>
+
+#include <health-impl/Health.h>
+#include "health-convert.h"
+
+namespace aidl::android::hardware::health {
+
+// Unlike the HIDL version android::hardware::health::V2_1::implementation::HalHealthLoop,
+// do not define HalHealthLoop::Init because we no longer have Health::getHealthConfig.
+// Let the Health class handle Init.
+void HalHealthLoop::Init(struct healthd_config* config) {
+    callback_->OnInit(this, config);
+}
+
+void HalHealthLoop::Heartbeat() {
+    callback_->OnHeartbeat();
+}
+
+void HalHealthLoop::ScheduleBatteryUpdate() {
+    // ignore errors. impl may not be able to handle any callbacks, so
+    // update() may return errors.
+    if (auto res = service_->update(); !res.isOk()) {
+        LOG(WARNING) << "update() on the health HAL implementation failed with "
+                     << res.getDescription();
+    }
+
+    HealthInfo health_info;
+    auto res = service_->getHealthInfo(&health_info);
+    CHECK(res.isOk()) << "getHealthInfo() on the health HAL implementation failed with "
+                      << res.getDescription();
+    OnHealthInfoChanged(health_info);
+}
+
+int HalHealthLoop::PrepareToWait() {
+    return callback_->OnPrepareToWait();
+}
+
+void HalHealthLoop::OnHealthInfoChanged(const HealthInfo& health_info) {
+    callback_->OnHealthInfoChanged(health_info);
+    set_charger_online(health_info);
+    AdjustWakealarmPeriods(charger_online());
+}
+
+void HalHealthLoop::set_charger_online(const HealthInfo& health_info) {
+    charger_online_ = health_info.chargerAcOnline || health_info.chargerUsbOnline ||
+                      health_info.chargerWirelessOnline || health_info.chargerDockOnline;
+}
+
+}  // namespace aidl::android::hardware::health
diff --git a/health/aidl/default/Health.cpp b/health/aidl/default/Health.cpp
new file mode 100644
index 0000000..d41d01a
--- /dev/null
+++ b/health/aidl/default/Health.cpp
@@ -0,0 +1,338 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "health-impl/Health.h"
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <android/hardware/health/translate-ndk.h>
+#include <health/utils.h>
+
+#include "LinkedCallback.h"
+#include "health-convert.h"
+
+using std::string_literals::operator""s;
+
+namespace aidl::android::hardware::health {
+
+namespace {
+// Wrap LinkedCallback::OnCallbackDied() into a void(void*).
+void OnCallbackDiedWrapped(void* cookie) {
+    LinkedCallback* linked = reinterpret_cast<LinkedCallback*>(cookie);
+    linked->OnCallbackDied();
+}
+}  // namespace
+
+/*
+// If you need to call healthd_board_init, construct the Health instance with
+// the healthd_config after calling healthd_board_init:
+class MyHealth : public Health {
+  protected:
+    MyHealth() : Health(CreateConfig()) {}
+  private:
+    static std::unique_ptr<healthd_config> CreateConfig() {
+      auto config = std::make_unique<healthd_config>();
+      ::android::hardware::health::InitHealthdConfig(config.get());
+      healthd_board_init(config.get());
+      return std::move(config);
+    }
+};
+*/
+Health::Health(std::string_view instance_name, std::unique_ptr<struct healthd_config>&& config)
+    : instance_name_(instance_name),
+      healthd_config_(std::move(config)),
+      death_recipient_(AIBinder_DeathRecipient_new(&OnCallbackDiedWrapped)) {
+    battery_monitor_.init(healthd_config_.get());
+}
+
+Health::~Health() {}
+
+//
+// Getters.
+//
+
+template <typename T>
+static ndk::ScopedAStatus GetProperty(::android::BatteryMonitor* monitor, int id, T defaultValue,
+                                      T* out) {
+    *out = defaultValue;
+    struct ::android::BatteryProperty prop;
+    ::android::status_t err = monitor->getProperty(static_cast<int>(id), &prop);
+    if (err == ::android::OK) {
+        *out = static_cast<T>(prop.valueInt64);
+    } else {
+        LOG(DEBUG) << "getProperty(" << id << ")"
+                   << " fails: (" << err << ") " << ::android::statusToString(err);
+    }
+
+    switch (err) {
+        case ::android::OK:
+            return ndk::ScopedAStatus::ok();
+        case ::android::NAME_NOT_FOUND:
+            return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+        default:
+            return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+                    IHealth::STATUS_UNKNOWN, ::android::statusToString(err).c_str());
+    }
+}
+
+ndk::ScopedAStatus Health::getChargeCounterUah(int32_t* out) {
+    return GetProperty<int32_t>(&battery_monitor_, ::android::BATTERY_PROP_CHARGE_COUNTER, 0, out);
+}
+
+ndk::ScopedAStatus Health::getCurrentNowMicroamps(int32_t* out) {
+    return GetProperty<int32_t>(&battery_monitor_, ::android::BATTERY_PROP_CURRENT_NOW, 0, out);
+}
+
+ndk::ScopedAStatus Health::getCurrentAverageMicroamps(int32_t* out) {
+    return GetProperty<int32_t>(&battery_monitor_, ::android::BATTERY_PROP_CURRENT_AVG, 0, out);
+}
+
+ndk::ScopedAStatus Health::getCapacity(int32_t* out) {
+    return GetProperty<int32_t>(&battery_monitor_, ::android::BATTERY_PROP_CAPACITY, 0, out);
+}
+
+ndk::ScopedAStatus Health::getEnergyCounterNwh(int64_t* out) {
+    return GetProperty<int64_t>(&battery_monitor_, ::android::BATTERY_PROP_ENERGY_COUNTER, 0, out);
+}
+
+ndk::ScopedAStatus Health::getChargeStatus(BatteryStatus* out) {
+    return GetProperty(&battery_monitor_, ::android::BATTERY_PROP_BATTERY_STATUS,
+                       BatteryStatus::UNKNOWN, out);
+}
+
+ndk::ScopedAStatus Health::getDiskStats(std::vector<DiskStats>*) {
+    // This implementation does not support DiskStats. An implementation may extend this
+    // class and override this function to support disk stats.
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus Health::getStorageInfo(std::vector<StorageInfo>*) {
+    // This implementation does not support StorageInfo. An implementation may extend this
+    // class and override this function to support storage info.
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus Health::getHealthInfo(HealthInfo* out) {
+    battery_monitor_.updateValues();
+
+    *out = battery_monitor_.getHealthInfo();
+
+    // Fill in storage infos; these aren't retrieved by BatteryMonitor.
+    if (auto res = getStorageInfo(&out->storageInfos); !res.isOk()) {
+        if (res.getServiceSpecificError() == 0 &&
+            res.getExceptionCode() != EX_UNSUPPORTED_OPERATION) {
+            return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+                    IHealth::STATUS_UNKNOWN,
+                    ("getStorageInfo fails: " + res.getDescription()).c_str());
+        }
+        LOG(DEBUG) << "getHealthInfo: getStorageInfo fails with service-specific error, clearing: "
+                   << res.getDescription();
+        out->storageInfos = {};
+    }
+    if (auto res = getDiskStats(&out->diskStats); !res.isOk()) {
+        if (res.getServiceSpecificError() == 0 &&
+            res.getExceptionCode() != EX_UNSUPPORTED_OPERATION) {
+            return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+                    IHealth::STATUS_UNKNOWN,
+                    ("getDiskStats fails: " + res.getDescription()).c_str());
+        }
+        LOG(DEBUG) << "getHealthInfo: getDiskStats fails with service-specific error, clearing: "
+                   << res.getDescription();
+        out->diskStats = {};
+    }
+
+    // A subclass may want to update health info struct before returning it.
+    UpdateHealthInfo(out);
+
+    return ndk::ScopedAStatus::ok();
+}
+
+binder_status_t Health::dump(int fd, const char**, uint32_t) {
+    battery_monitor_.dumpState(fd);
+
+    ::android::base::WriteStringToFd("\ngetHealthInfo -> ", fd);
+    HealthInfo health_info;
+    auto res = getHealthInfo(&health_info);
+    if (res.isOk()) {
+        ::android::base::WriteStringToFd(health_info.toString(), fd);
+    } else {
+        ::android::base::WriteStringToFd(res.getDescription(), fd);
+    }
+
+    fsync(fd);
+    return STATUS_OK;
+}
+
+std::optional<bool> Health::ShouldKeepScreenOn() {
+    if (!healthd_config_->screen_on) {
+        return std::nullopt;
+    }
+
+    HealthInfo health_info;
+    auto res = getHealthInfo(&health_info);
+    if (!res.isOk()) {
+        return std::nullopt;
+    }
+
+    ::android::BatteryProperties props = {};
+    convert(health_info, &props);
+    return healthd_config_->screen_on(&props);
+}
+
+namespace {
+bool IsDeadObjectLogged(const ndk::ScopedAStatus& ret) {
+    if (ret.isOk()) return false;
+    if (ret.getStatus() == ::STATUS_DEAD_OBJECT) return true;
+    LOG(ERROR) << "Cannot call healthInfoChanged on callback: " << ret.getDescription();
+    return false;
+}
+}  // namespace
+
+//
+// Subclass helpers / overrides
+//
+
+void Health::UpdateHealthInfo(HealthInfo* /* health_info */) {
+    /*
+        // Sample code for a subclass to implement this:
+        // If you need to modify values (e.g. batteryChargeTimeToFullNowSeconds), do it here.
+        health_info->batteryChargeTimeToFullNowSeconds = calculate_charge_time_seconds();
+
+        // If you need to call healthd_board_battery_update, modify its signature
+        // and implementation to operate on HealthInfo directly, then call:
+        healthd_board_battery_update(health_info);
+    */
+}
+
+//
+// Methods that handle callbacks.
+//
+
+ndk::ScopedAStatus Health::registerCallback(const std::shared_ptr<IHealthInfoCallback>& callback) {
+    if (callback == nullptr) {
+        // For now, this shouldn't happen because argument is not nullable.
+        return ndk::ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
+    }
+
+    {
+        std::lock_guard<decltype(callbacks_lock_)> lock(callbacks_lock_);
+        callbacks_.emplace_back(LinkedCallback::Make(ref<Health>(), callback));
+        // unlock
+    }
+
+    HealthInfo health_info;
+    if (auto res = getHealthInfo(&health_info); !res.isOk()) {
+        LOG(WARNING) << "Cannot call getHealthInfo: " << res.getDescription();
+        // No health info to send, so return early.
+        return ndk::ScopedAStatus::ok();
+    }
+
+    if (auto res = callback->healthInfoChanged(health_info); IsDeadObjectLogged(res)) {
+        (void)unregisterCallback(callback);
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Health::unregisterCallback(
+        const std::shared_ptr<IHealthInfoCallback>& callback) {
+    if (callback == nullptr) {
+        // For now, this shouldn't happen because argument is not nullable.
+        return ndk::ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
+    }
+
+    std::lock_guard<decltype(callbacks_lock_)> lock(callbacks_lock_);
+
+    auto matches = [callback](const auto& linked) {
+        return linked->callback()->asBinder() == callback->asBinder();  // compares binder object
+    };
+    auto it = std::remove_if(callbacks_.begin(), callbacks_.end(), matches);
+    bool removed = (it != callbacks_.end());
+    callbacks_.erase(it, callbacks_.end());  // calls unlinkToDeath on deleted callbacks.
+    return removed ? ndk::ScopedAStatus::ok()
+                   : ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+}
+
+// A combination of the HIDL version
+//   android::hardware::health::V2_1::implementation::Health::update() and
+//   android::hardware::health::V2_1::implementation::BinderHealth::update()
+ndk::ScopedAStatus Health::update() {
+    HealthInfo health_info;
+    if (auto res = getHealthInfo(&health_info); !res.isOk()) {
+        LOG(DEBUG) << "Cannot call getHealthInfo for update(): " << res.getDescription();
+        // Propagate service specific errors. If there's none, report unknown error.
+        if (res.getServiceSpecificError() != 0 ||
+            res.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
+            return res;
+        }
+        return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+                IHealth::STATUS_UNKNOWN, res.getDescription().c_str());
+    }
+    battery_monitor_.logValues();
+    OnHealthInfoChanged(health_info);
+    return ndk::ScopedAStatus::ok();
+}
+
+void Health::OnHealthInfoChanged(const HealthInfo& health_info) {
+    // Notify all callbacks
+    std::unique_lock<decltype(callbacks_lock_)> lock(callbacks_lock_);
+    // is_dead notifies a callback and return true if it is dead.
+    auto is_dead = [&](const auto& linked) {
+        auto res = linked->callback()->healthInfoChanged(health_info);
+        return IsDeadObjectLogged(res);
+    };
+    auto it = std::remove_if(callbacks_.begin(), callbacks_.end(), is_dead);
+    callbacks_.erase(it, callbacks_.end());  // calls unlinkToDeath on deleted callbacks.
+    lock.unlock();
+
+    // Let HalHealthLoop::OnHealthInfoChanged() adjusts uevent / wakealarm periods
+}
+
+void Health::BinderEvent(uint32_t /*epevents*/) {
+    if (binder_fd_ >= 0) {
+        ABinderProcess_handlePolledCommands();
+    }
+}
+
+void Health::OnInit(HalHealthLoop* hal_health_loop, struct healthd_config* config) {
+    LOG(INFO) << instance_name_ << " instance initializing with healthd_config...";
+
+    // Similar to HIDL's android::hardware::health::V2_1::implementation::HalHealthLoop::Init,
+    // copy configuration parameters to |config| for HealthLoop (e.g. uevent / wake alarm periods)
+    *config = *healthd_config_.get();
+
+    binder_status_t status = ABinderProcess_setupPolling(&binder_fd_);
+
+    if (status == ::STATUS_OK && binder_fd_ >= 0) {
+        std::shared_ptr<Health> thiz = ref<Health>();
+        auto binder_event = [thiz](auto*, uint32_t epevents) { thiz->BinderEvent(epevents); };
+        if (hal_health_loop->RegisterEvent(binder_fd_, binder_event, EVENT_NO_WAKEUP_FD) != 0) {
+            PLOG(ERROR) << instance_name_ << " instance: Register for binder events failed";
+        }
+    }
+
+    std::string health_name = IHealth::descriptor + "/"s + instance_name_;
+    CHECK_EQ(STATUS_OK, AServiceManager_addService(this->asBinder().get(), health_name.c_str()))
+            << instance_name_ << ": Failed to register HAL";
+
+    LOG(INFO) << instance_name_ << ": Hal init done";
+}
+
+// Unlike hwbinder, for binder, there's no need to explicitly call flushCommands()
+// in PrepareToWait(). See b/139697085.
+
+}  // namespace aidl::android::hardware::health
diff --git a/health/aidl/default/LinkedCallback.cpp b/health/aidl/default/LinkedCallback.cpp
new file mode 100644
index 0000000..2985ffe
--- /dev/null
+++ b/health/aidl/default/LinkedCallback.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <android/binder_ibinder.h>
+
+#include <health-impl/Health.h>
+#include <utils/Errors.h>
+
+#include "LinkedCallback.h"
+
+namespace aidl::android::hardware::health {
+
+std::unique_ptr<LinkedCallback> LinkedCallback::Make(
+        std::shared_ptr<Health> service, std::shared_ptr<IHealthInfoCallback> callback) {
+    std::unique_ptr<LinkedCallback> ret(new LinkedCallback());
+    binder_status_t linkRet =
+            AIBinder_linkToDeath(callback->asBinder().get(), service->death_recipient_.get(),
+                                 reinterpret_cast<void*>(ret.get()));
+    if (linkRet != ::STATUS_OK) {
+        LOG(WARNING) << __func__ << "Cannot link to death: " << linkRet;
+        return nullptr;
+    }
+    ret->service_ = service;
+    ret->callback_ = std::move(callback);
+    return ret;
+}
+
+LinkedCallback::LinkedCallback() = default;
+
+LinkedCallback::~LinkedCallback() {
+    if (callback_ == nullptr) {
+        return;
+    }
+    auto status =
+            AIBinder_unlinkToDeath(callback_->asBinder().get(), service()->death_recipient_.get(),
+                                   reinterpret_cast<void*>(this));
+    if (status != STATUS_OK && status != STATUS_DEAD_OBJECT) {
+        LOG(WARNING) << __func__ << "Cannot unlink to death: " << ::android::statusToString(status);
+    }
+}
+
+std::shared_ptr<Health> LinkedCallback::service() {
+    auto service_sp = service_.lock();
+    CHECK_NE(nullptr, service_sp);
+    return service_sp;
+}
+
+void LinkedCallback::OnCallbackDied() {
+    service()->unregisterCallback(callback_);
+}
+
+}  // namespace aidl::android::hardware::health
diff --git a/health/aidl/default/LinkedCallback.h b/health/aidl/default/LinkedCallback.h
new file mode 100644
index 0000000..82490a7
--- /dev/null
+++ b/health/aidl/default/LinkedCallback.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <memory>
+
+#include <aidl/android/hardware/health/IHealthInfoCallback.h>
+#include <android-base/macros.h>
+#include <android/binder_auto_utils.h>
+
+#include <health-impl/Health.h>
+
+namespace aidl::android::hardware::health {
+
+// Type of the cookie pointer in linkToDeath.
+// A (Health, IHealthInfoCallback) tuple.
+class LinkedCallback {
+  public:
+    // Automatically linkToDeath upon construction with the returned object as the cookie.
+    // service->death_reciepient() should be from CreateDeathRecipient().
+    // Not using a strong reference to |service| to avoid circular reference. The lifetime
+    // of |service| must be longer than this LinkedCallback object.
+    static std::unique_ptr<LinkedCallback> Make(std::shared_ptr<Health> service,
+                                                std::shared_ptr<IHealthInfoCallback> callback);
+
+    // Automatically unlinkToDeath upon destruction. So, it is always safe to reinterpret_cast
+    // the cookie back to the LinkedCallback object.
+    ~LinkedCallback();
+
+    // The wrapped IHealthInfoCallback object.
+    const std::shared_ptr<IHealthInfoCallback>& callback() const { return callback_; }
+
+    // On callback died, unreigster it from the service.
+    void OnCallbackDied();
+
+  private:
+    LinkedCallback();
+    DISALLOW_COPY_AND_ASSIGN(LinkedCallback);
+
+    std::shared_ptr<Health> service();
+
+    std::weak_ptr<Health> service_;
+    std::shared_ptr<IHealthInfoCallback> callback_;
+};
+
+}  // namespace aidl::android::hardware::health
diff --git a/health/aidl/default/android.hardware.health-service.example.rc b/health/aidl/default/android.hardware.health-service.example.rc
new file mode 100644
index 0000000..e052024
--- /dev/null
+++ b/health/aidl/default/android.hardware.health-service.example.rc
@@ -0,0 +1,17 @@
+service vendor.health-default /vendor/bin/hw/android.hardware.health-service.example
+    class hal
+    user system
+    group system
+    capabilities WAKE_ALARM BLOCK_SUSPEND
+    file /dev/kmsg w
+
+service vendor.charger /vendor/bin/hw/android.hardware.health-service.example --charger
+    class charger
+    seclabel u:r:charger_vendor:s0
+    user system
+    group system wakelock input
+    capabilities SYS_BOOT
+    file /dev/kmsg w
+    file /sys/fs/pstore/console-ramoops-0 r
+    file /sys/fs/pstore/console-ramoops r
+    file /proc/last_kmsg r
diff --git a/health/aidl/default/android.hardware.health-service.example.xml b/health/aidl/default/android.hardware.health-service.example.xml
new file mode 100644
index 0000000..98026cb
--- /dev/null
+++ b/health/aidl/default/android.hardware.health-service.example.xml
@@ -0,0 +1,7 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.health</name>
+        <version>1</version>
+        <fqname>IHealth/default</fqname>
+    </hal>
+</manifest>
diff --git a/health/aidl/default/android.hardware.health-service.example_recovery.rc b/health/aidl/default/android.hardware.health-service.example_recovery.rc
new file mode 100644
index 0000000..0001170
--- /dev/null
+++ b/health/aidl/default/android.hardware.health-service.example_recovery.rc
@@ -0,0 +1,7 @@
+service vendor.health-default /system/bin/hw/android.hardware.health-service.example_recovery
+    class hal
+    seclabel u:r:hal_health_default:s0
+    user system
+    group system
+    capabilities WAKE_ALARM BLOCK_SUSPEND
+    file /dev/kmsg w
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/aidl/default/health-convert.cpp b/health/aidl/default/health-convert.cpp
new file mode 100644
index 0000000..6118865
--- /dev/null
+++ b/health/aidl/default/health-convert.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "health-convert.h"
+
+namespace aidl::android::hardware::health {
+
+void convert(const HealthInfo& info, struct ::android::BatteryProperties* p) {
+    p->chargerAcOnline = info.chargerAcOnline;
+    p->chargerUsbOnline = info.chargerUsbOnline;
+    p->chargerWirelessOnline = info.chargerWirelessOnline;
+    p->chargerDockOnline = info.chargerDockOnline;
+    p->maxChargingCurrent = info.maxChargingCurrentMicroamps;
+    p->maxChargingVoltage = info.maxChargingVoltageMicrovolts;
+    p->batteryStatus = static_cast<int>(info.batteryStatus);
+    p->batteryHealth = static_cast<int>(info.batteryHealth);
+    p->batteryPresent = info.batteryPresent;
+    p->batteryLevel = info.batteryLevel;
+    p->batteryVoltage = info.batteryVoltageMillivolts;
+    p->batteryTemperature = info.batteryTemperatureTenthsCelsius;
+    p->batteryCurrent = info.batteryCurrentMicroamps;
+    p->batteryCycleCount = info.batteryCycleCount;
+    p->batteryFullCharge = info.batteryFullChargeUah;
+    p->batteryChargeCounter = info.batteryChargeCounterUah;
+    p->batteryTechnology = ::android::String8(info.batteryTechnology.c_str());
+}
+
+}  // namespace aidl::android::hardware::health
diff --git a/health/aidl/default/health-convert.h b/health/aidl/default/health-convert.h
new file mode 100644
index 0000000..179ffc4
--- /dev/null
+++ b/health/aidl/default/health-convert.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/health/HealthInfo.h>
+#include <batteryservice/BatteryService.h>
+#include <healthd/healthd.h>
+
+// Conversion between healthd types and AIDL health HAL types. Note that most
+// of the conversion loses information, because these types have a different
+// set of information.
+
+namespace aidl::android::hardware::health {
+
+void convert(const HealthInfo& info, struct ::android::BatteryProperties* out);
+
+}  // namespace aidl::android::hardware::health
diff --git a/health/aidl/default/include/health-impl/ChargerUtils.h b/health/aidl/default/include/health-impl/ChargerUtils.h
new file mode 100644
index 0000000..8f94181
--- /dev/null
+++ b/health/aidl/default/include/health-impl/ChargerUtils.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <optional>
+#include <type_traits>
+
+#include <android/binder_auto_utils.h>
+#include <charger/healthd_mode_charger.h>
+#include <health-impl/Health.h>
+
+#pragma once
+
+namespace aidl::android::hardware::health::charger {
+
+// Implements ChargerHalHealthLoopInterface for AIDL charger
+// Adapter of (Health, HalHealthLoop) -> ChargerHalHealthLoopInterface
+class ChargerCallback : public ::android::ChargerConfigurationInterface {
+  public:
+    ChargerCallback(const std::shared_ptr<Health>& service) : service_(service) {}
+    std::optional<bool> ChargerShouldKeepScreenOn() override;
+    bool ChargerIsOnline() override;
+    void ChargerInitConfig(healthd_config* config) override;
+    int ChargerRegisterEvent(int fd, BoundFunction func, EventWakeup wakeup) override;
+
+    // Override to return true to replace `ro.charger.enable_suspend=true`
+    bool ChargerEnableSuspend() override { return false; }
+
+    void set_hal_health_loop(const std::weak_ptr<HalHealthLoop>& hal_health_loop);
+
+  private:
+    std::shared_ptr<Health> service_;
+    std::weak_ptr<HalHealthLoop> hal_health_loop_;
+};
+
+int ChargerModeMain(const std::shared_ptr<Health>& binder,
+                    const std::shared_ptr<ChargerCallback>& charger_callback);
+
+}  // namespace aidl::android::hardware::health::charger
diff --git a/health/aidl/default/include/health-impl/HalHealthLoop.h b/health/aidl/default/include/health-impl/HalHealthLoop.h
new file mode 100644
index 0000000..c46aaa4
--- /dev/null
+++ b/health/aidl/default/include/health-impl/HalHealthLoop.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <memory>
+#include <optional>
+
+#include <aidl/android/hardware/health/IHealth.h>
+#include <health/HealthLoop.h>
+
+namespace aidl::android::hardware::health {
+
+class HalHealthLoop;
+
+class HalHealthLoopCallback {
+  public:
+    virtual ~HalHealthLoopCallback() = default;
+
+    // Called by HalHealthLoop::Init
+    virtual void OnInit(HalHealthLoop* hal_health_loop, struct healthd_config* config) = 0;
+    // Called by HalHealthLoop::Heartbeat
+    virtual void OnHeartbeat(){};
+    // Called by HalHealthLoop::PrepareToWait
+    virtual int OnPrepareToWait() { return -1; }
+    // Called by HalHealthLoop::ScheduleBatteryUpdate
+    virtual void OnHealthInfoChanged(const HealthInfo&) {}
+};
+
+// AIDL version of android::hardware::health::V2_1::implementation::HalHealthLoop.
+// An implementation of HealthLoop for using a given health HAL.
+class HalHealthLoop final : public ::android::hardware::health::HealthLoop {
+  public:
+    // Caller must ensure that the lifetime of service_ is not shorter than this object.
+    HalHealthLoop(std::shared_ptr<IHealth> service, std::shared_ptr<HalHealthLoopCallback> callback)
+        : service_(std::move(service)), callback_(std::move(callback)) {}
+
+    using HealthLoop::RegisterEvent;
+
+    bool charger_online() const { return charger_online_; }
+
+  protected:
+    virtual void Init(struct healthd_config* config) override;
+    virtual void Heartbeat() override;
+    virtual int PrepareToWait() override;
+    virtual void ScheduleBatteryUpdate() override;
+
+  private:
+    std::shared_ptr<IHealth> service_;
+    std::shared_ptr<HalHealthLoopCallback> callback_;
+    bool charger_online_ = false;
+
+    // Helpers of OnHealthInfoChanged.
+    void set_charger_online(const HealthInfo& health_info);
+
+    // HealthLoop periodically calls ScheduleBatteryUpdate, which calls
+    // OnHealthInfoChanged callback. A subclass of the callback can override
+    // HalHealthLoopCallback::OnHealthInfoChanged to
+    // broadcast the health_info to interested listeners.
+    // This adjust uevents / wakealarm periods.
+    void OnHealthInfoChanged(const HealthInfo& health_info);
+};
+
+}  // namespace aidl::android::hardware::health
diff --git a/health/aidl/default/include/health-impl/Health.h b/health/aidl/default/include/health-impl/Health.h
new file mode 100644
index 0000000..6bd4946
--- /dev/null
+++ b/health/aidl/default/include/health-impl/Health.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <memory>
+#include <optional>
+
+#include <aidl/android/hardware/health/BnHealth.h>
+#include <aidl/android/hardware/health/IHealthInfoCallback.h>
+#include <android/binder_auto_utils.h>
+#include <health-impl/HalHealthLoop.h>
+#include <healthd/BatteryMonitor.h>
+#include <healthd/healthd.h>
+
+namespace aidl::android::hardware::health {
+
+class LinkedCallback;
+
+// AIDL version of android::hardware::health::V2_1::implementation::Health and BinderHealth.
+// There's no need to separate the two in AIDL because AIDL does not support passthrough transport.
+//
+// Instead of inheriting from HalHealthLoop directly, implements the callback interface to
+// HalHealthLoop instead.
+//
+// Sample implementation of health HAL.
+class Health : public BnHealth, public HalHealthLoopCallback {
+  public:
+    // Initialize with |config|.
+    // A subclass may modify |config| before passing it to the parent constructor.
+    // See implementation of Health for code samples.
+    Health(std::string_view instance_name, std::unique_ptr<struct healthd_config>&& config);
+    virtual ~Health();
+
+    ndk::ScopedAStatus registerCallback(
+            const std::shared_ptr<IHealthInfoCallback>& callback) override;
+    ndk::ScopedAStatus unregisterCallback(
+            const std::shared_ptr<IHealthInfoCallback>& callback) override;
+    ndk::ScopedAStatus update() override;
+
+    // A subclass should not override this. Override UpdateHealthInfo instead.
+    ndk::ScopedAStatus getHealthInfo(HealthInfo* out) override final;
+
+    // A subclass is recommended to override the path in healthd_config in the constructor.
+    // Only override these if there are no suitable kernel interfaces to read these values.
+    ndk::ScopedAStatus getChargeCounterUah(int32_t* out) override;
+    ndk::ScopedAStatus getCurrentNowMicroamps(int32_t* out) override;
+    ndk::ScopedAStatus getCurrentAverageMicroamps(int32_t* out) override;
+    ndk::ScopedAStatus getCapacity(int32_t* out) override;
+    ndk::ScopedAStatus getChargeStatus(BatteryStatus* out) override;
+
+    // A subclass may either override these or provide function pointers in
+    // in healthd_config in the constructor.
+    // Prefer overriding these for efficiency.
+    ndk::ScopedAStatus getEnergyCounterNwh(int64_t* out) override;
+
+    // A subclass may override these for a specific device.
+    // The default implementations return nothing in |out|.
+    ndk::ScopedAStatus getDiskStats(std::vector<DiskStats>* out) override;
+    ndk::ScopedAStatus getStorageInfo(std::vector<StorageInfo>* out) override;
+
+    // A subclass may override these to provide a different implementation.
+    binder_status_t dump(int fd, const char** args, uint32_t num_args) override;
+
+    // HalHealthLoopCallback implementation.
+    void OnInit(HalHealthLoop* hal_health_loop, struct healthd_config* config) override;
+    void OnHealthInfoChanged(const HealthInfo& health_info) override;
+
+    // A subclass may override this if it wants to handle binder events differently.
+    virtual void BinderEvent(uint32_t epevents);
+
+    // A subclass may override this to determine whether screen should be kept on in charger mode.
+    // Default is to invoke healthd_config->screen_on() on the BatteryProperties converted
+    // from getHealthInfo.
+    // Prefer overriding these to providing screen_on in healthd_config in the constructor
+    // for efficiency.
+    virtual std::optional<bool> ShouldKeepScreenOn();
+
+  protected:
+    // A subclass can override this to modify any health info object before
+    // returning to clients. This is similar to healthd_board_battery_update().
+    // By default, it does nothing.
+    // See implementation of Health for code samples.
+    virtual void UpdateHealthInfo(HealthInfo* health_info);
+
+  private:
+    friend LinkedCallback;  // for exposing death_recipient_
+
+    bool unregisterCallbackInternal(std::shared_ptr<IHealthInfoCallback> callback);
+
+    std::string instance_name_;
+    ::android::BatteryMonitor battery_monitor_;
+    std::unique_ptr<struct healthd_config> healthd_config_;
+
+    ndk::ScopedAIBinder_DeathRecipient death_recipient_;
+    int binder_fd_ = -1;
+    std::mutex callbacks_lock_;
+    std::vector<std::unique_ptr<LinkedCallback>> callbacks_;
+};
+
+}  // namespace aidl::android::hardware::health
diff --git a/health/aidl/default/main.cpp b/health/aidl/default/main.cpp
new file mode 100644
index 0000000..03b2ecb
--- /dev/null
+++ b/health/aidl/default/main.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <android/binder_interface_utils.h>
+#include <health-impl/Health.h>
+#include <health/utils.h>
+
+#ifndef CHARGER_FORCE_NO_UI
+#define CHARGER_FORCE_NO_UI 0
+#endif
+
+#if !CHARGER_FORCE_NO_UI
+#include <health-impl/ChargerUtils.h>
+#endif
+
+using aidl::android::hardware::health::HalHealthLoop;
+using aidl::android::hardware::health::Health;
+
+#if !CHARGER_FORCE_NO_UI
+using aidl::android::hardware::health::charger::ChargerCallback;
+using aidl::android::hardware::health::charger::ChargerModeMain;
+#endif
+
+static constexpr const char* gInstanceName = "default";
+static constexpr std::string_view gChargerArg{"--charger"};
+
+int main(int argc, char** argv) {
+#ifdef __ANDROID_RECOVERY__
+    android::base::InitLogging(argv, android::base::KernelLogger);
+#endif
+
+    // make a default health service
+    auto config = std::make_unique<healthd_config>();
+    ::android::hardware::health::InitHealthdConfig(config.get());
+    auto binder = ndk::SharedRefBase::make<Health>(gInstanceName, std::move(config));
+
+    if (argc >= 2 && argv[1] == gChargerArg) {
+#if !CHARGER_FORCE_NO_UI
+        // If charger shouldn't have UI for your device, simply drop the line below
+        // for your service implementation. This corresponds to
+        // ro.charger.no_ui=true
+        return ChargerModeMain(binder, std::make_shared<ChargerCallback>(binder));
+#endif
+
+        LOG(INFO) << "Starting charger mode without UI.";
+    } else {
+        LOG(INFO) << "Starting health HAL.";
+    }
+
+    auto hal_health_loop = std::make_shared<HalHealthLoop>(binder, binder);
+    return hal_health_loop->StartLoop();
+}
diff --git a/health/aidl/include/android/hardware/health/translate-ndk.h b/health/aidl/include/android/hardware/health/translate-ndk.h
new file mode 100644
index 0000000..91add42
--- /dev/null
+++ b/health/aidl/include/android/hardware/health/translate-ndk.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/health/BatteryCapacityLevel.h>
+#include <aidl/android/hardware/health/DiskStats.h>
+#include <aidl/android/hardware/health/HealthInfo.h>
+#include <aidl/android/hardware/health/StorageInfo.h>
+#include <android/hardware/health/2.0/types.h>
+#include <android/hardware/health/2.1/types.h>
+#include <limits>
+
+namespace android::h2a {
+
+__attribute__((warn_unused_result)) bool translate(
+        const ::android::hardware::health::V2_0::StorageInfo& in,
+        aidl::android::hardware::health::StorageInfo* out);
+__attribute__((warn_unused_result)) bool translate(
+        const ::android::hardware::health::V2_0::DiskStats& in,
+        aidl::android::hardware::health::DiskStats* out);
+__attribute__((warn_unused_result)) bool translate(
+        const ::android::hardware::health::V2_0::HealthInfo& in,
+        aidl::android::hardware::health::HealthInfo* out);
+__attribute__((warn_unused_result)) bool translate(
+        const ::android::hardware::health::V2_1::HealthInfo& in,
+        aidl::android::hardware::health::HealthInfo* out);
+
+}  // namespace android::h2a
diff --git a/health/aidl/vts/functional/Android.bp b/health/aidl/vts/functional/Android.bp
new file mode 100644
index 0000000..f9da79f
--- /dev/null
+++ b/health/aidl/vts/functional/Android.bp
@@ -0,0 +1,52 @@
+//
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+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: "VtsHalHealthTargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    tidy_timeout_srcs: [
+        "VtsHalHealthTargetTest.cpp",
+    ],
+    srcs: [
+        "VtsHalHealthTargetTest.cpp",
+    ],
+    shared_libs: [
+        "libbinder_ndk",
+    ],
+    static_libs: [
+        "android.hardware.health-V1-ndk",
+        "libgmock",
+    ],
+    header_libs: [
+        "libhealthtest_headers",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
diff --git a/health/aidl/vts/functional/VtsHalHealthTargetTest.cpp b/health/aidl/vts/functional/VtsHalHealthTargetTest.cpp
new file mode 100644
index 0000000..3e07188
--- /dev/null
+++ b/health/aidl/vts/functional/VtsHalHealthTargetTest.cpp
@@ -0,0 +1,539 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "health_aidl_hal_test"
+
+#include <chrono>
+#include <memory>
+#include <thread>
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/health/BnHealthInfoCallback.h>
+#include <aidl/android/hardware/health/IHealth.h>
+#include <android/binder_auto_utils.h>
+#include <android/binder_enums.h>
+#include <android/binder_interface_utils.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <health-test/TestUtils.h>
+
+using android::getAidlHalInstanceNames;
+using android::PrintInstanceNameToString;
+using android::hardware::health::test_utils::SucceedOnce;
+using ndk::enum_range;
+using ndk::ScopedAStatus;
+using ndk::SharedRefBase;
+using ndk::SpAIBinder;
+using testing::AllOf;
+using testing::AnyOf;
+using testing::AnyOfArray;
+using testing::AssertionFailure;
+using testing::AssertionResult;
+using testing::AssertionSuccess;
+using testing::Contains;
+using testing::Each;
+using testing::Eq;
+using testing::ExplainMatchResult;
+using testing::Ge;
+using testing::Gt;
+using testing::Le;
+using testing::Lt;
+using testing::Matcher;
+using testing::Not;
+using namespace std::string_literals;
+using namespace std::chrono_literals;
+
+namespace aidl::android::hardware::health {
+
+static constexpr int32_t kFullChargeDesignCapMinUah = 100 * 1000;
+static constexpr int32_t kFullChargeDesignCapMaxUah = 100 * 1000 * 1000;
+
+MATCHER(IsOk, "") {
+    *result_listener << "status is " << arg.getDescription();
+    return arg.isOk();
+}
+
+MATCHER_P(ExceptionIs, exception_code, "") {
+    *result_listener << "status is " << arg.getDescription();
+    return arg.getExceptionCode() == exception_code;
+}
+
+template <typename T>
+Matcher<T> InClosedRange(const T& lo, const T& hi) {
+    return AllOf(Ge(lo), Le(hi));
+}
+
+template <typename T>
+Matcher<T> IsValidEnum() {
+    return AnyOfArray(enum_range<T>().begin(), enum_range<T>().end());
+}
+
+class HealthAidl : public testing::TestWithParam<std::string> {
+  public:
+    void SetUp() override {
+        SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str()));
+        health = IHealth::fromBinder(binder);
+        ASSERT_NE(health, nullptr);
+    }
+    std::shared_ptr<IHealth> health;
+};
+
+class Callback : public BnHealthInfoCallback {
+  public:
+    ScopedAStatus healthInfoChanged(const HealthInfo&) override {
+        {
+            std::lock_guard<std::mutex> lock(mutex_);
+            invoked_ = true;
+        }
+        invoked_notify_.notify_all();
+        return ScopedAStatus::ok();
+    }
+    template <typename R, typename P>
+    [[nodiscard]] bool waitInvoke(std::chrono::duration<R, P> duration) {
+        std::unique_lock<std::mutex> lock(mutex_);
+        bool r = invoked_notify_.wait_for(lock, duration, [this] { return this->invoked_; });
+        invoked_ = false;
+        return r;
+    }
+
+  private:
+    std::mutex mutex_;
+    std::condition_variable invoked_notify_;
+    bool invoked_ = false;
+};
+
+TEST_P(HealthAidl, Callbacks) {
+    auto first_callback = SharedRefBase::make<Callback>();
+    auto second_callback = SharedRefBase::make<Callback>();
+
+    ASSERT_THAT(health->registerCallback(first_callback), IsOk());
+    ASSERT_THAT(health->registerCallback(second_callback), IsOk());
+
+    // registerCallback may or may not invoke the callback immediately, so the test needs
+    // to wait for the invocation. If the implementation chooses not to invoke the callback
+    // immediately, just wait for some time.
+    (void)first_callback->waitInvoke(200ms);
+    (void)second_callback->waitInvoke(200ms);
+
+    // assert that the first callback is invoked when update is called.
+    ASSERT_THAT(health->update(), IsOk());
+
+    ASSERT_TRUE(first_callback->waitInvoke(1s));
+    ASSERT_TRUE(second_callback->waitInvoke(1s));
+
+    ASSERT_THAT(health->unregisterCallback(first_callback), IsOk());
+
+    // clear any potentially pending callbacks result from wakealarm / kernel events
+    // If there is none, just wait for some time.
+    (void)first_callback->waitInvoke(200ms);
+    (void)second_callback->waitInvoke(200ms);
+
+    // assert that the second callback is still invoked even though the first is unregistered.
+    ASSERT_THAT(health->update(), IsOk());
+
+    ASSERT_FALSE(first_callback->waitInvoke(200ms));
+    ASSERT_TRUE(second_callback->waitInvoke(1s));
+
+    ASSERT_THAT(health->unregisterCallback(second_callback), IsOk());
+}
+
+TEST_P(HealthAidl, UnregisterNonExistentCallback) {
+    auto callback = SharedRefBase::make<Callback>();
+    auto ret = health->unregisterCallback(callback);
+    ASSERT_THAT(ret, ExceptionIs(EX_ILLEGAL_ARGUMENT));
+}
+
+/*
+ * Tests the values returned by getChargeCounterUah() from interface IHealth.
+ */
+TEST_P(HealthAidl, getChargeCounterUah) {
+    int32_t value;
+    auto status = health->getChargeCounterUah(&value);
+    ASSERT_THAT(status, AnyOf(IsOk(), ExceptionIs(EX_UNSUPPORTED_OPERATION)));
+    if (!status.isOk()) return;
+    ASSERT_THAT(value, Ge(0));
+}
+
+/*
+ * Tests the values returned by getCurrentNowMicroamps() from interface IHealth.
+ */
+TEST_P(HealthAidl, getCurrentNowMicroamps) {
+    int32_t value;
+    auto status = health->getCurrentNowMicroamps(&value);
+    ASSERT_THAT(status, AnyOf(IsOk(), ExceptionIs(EX_UNSUPPORTED_OPERATION)));
+    if (!status.isOk()) return;
+    ASSERT_THAT(value, Not(INT32_MIN));
+}
+
+/*
+ * Tests the values returned by getCurrentAverageMicroamps() from interface IHealth.
+ */
+TEST_P(HealthAidl, getCurrentAverageMicroamps) {
+    int32_t value;
+    auto status = health->getCurrentAverageMicroamps(&value);
+    ASSERT_THAT(status, AnyOf(IsOk(), ExceptionIs(EX_UNSUPPORTED_OPERATION)));
+    if (!status.isOk()) return;
+    ASSERT_THAT(value, Not(INT32_MIN));
+}
+
+/*
+ * Tests the values returned by getCapacity() from interface IHealth.
+ */
+TEST_P(HealthAidl, getCapacity) {
+    int32_t value;
+    auto status = health->getCapacity(&value);
+    ASSERT_THAT(status, AnyOf(IsOk(), ExceptionIs(EX_UNSUPPORTED_OPERATION)));
+    if (!status.isOk()) return;
+    ASSERT_THAT(value, InClosedRange(0, 100));
+}
+
+/*
+ * Tests the values returned by getEnergyCounterNwh() from interface IHealth.
+ */
+TEST_P(HealthAidl, getEnergyCounterNwh) {
+    int64_t value;
+    auto status = health->getEnergyCounterNwh(&value);
+    ASSERT_THAT(status, AnyOf(IsOk(), ExceptionIs(EX_UNSUPPORTED_OPERATION)));
+    if (!status.isOk()) return;
+    ASSERT_THAT(value, Not(INT64_MIN));
+}
+
+/*
+ * Tests the values returned by getChargeStatus() from interface IHealth.
+ */
+TEST_P(HealthAidl, getChargeStatus) {
+    BatteryStatus value;
+    auto status = health->getChargeStatus(&value);
+    ASSERT_THAT(status, AnyOf(IsOk(), ExceptionIs(EX_UNSUPPORTED_OPERATION)));
+    if (!status.isOk()) return;
+    ASSERT_THAT(value, IsValidEnum<BatteryStatus>());
+}
+
+MATCHER(IsValidStorageInfo, "") {
+    *result_listener << "value is " << arg.toString() << ".";
+    if (!ExplainMatchResult(InClosedRange(0, 3), arg.eol, result_listener)) {
+        *result_listener << " for eol.";
+        return false;
+    }
+    if (!ExplainMatchResult(InClosedRange(0, 0x0B), arg.lifetimeA, result_listener)) {
+        *result_listener << " for lifetimeA.";
+        return false;
+    }
+    if (!ExplainMatchResult(InClosedRange(0, 0x0B), arg.lifetimeB, result_listener)) {
+        *result_listener << " for lifetimeB.";
+        return false;
+    }
+    return true;
+}
+
+/*
+ * Tests the values returned by getStorageInfo() from interface IHealth.
+ */
+TEST_P(HealthAidl, getStorageInfo) {
+    std::vector<StorageInfo> value;
+    auto status = health->getStorageInfo(&value);
+    ASSERT_THAT(status, AnyOf(IsOk(), ExceptionIs(EX_UNSUPPORTED_OPERATION)));
+    if (!status.isOk()) return;
+    ASSERT_THAT(value, Each(IsValidStorageInfo()));
+}
+
+/*
+ * Tests the values returned by getDiskStats() from interface IHealth.
+ */
+TEST_P(HealthAidl, getDiskStats) {
+    std::vector<DiskStats> value;
+    auto status = health->getDiskStats(&value);
+    ASSERT_THAT(status, AnyOf(IsOk(), ExceptionIs(EX_UNSUPPORTED_OPERATION)));
+}
+
+MATCHER(IsValidHealthInfo, "") {
+    *result_listener << "value is " << arg.toString() << ".";
+    if (!ExplainMatchResult(Each(IsValidStorageInfo()), arg.storageInfos, result_listener)) {
+        *result_listener << " for storageInfos.";
+        return false;
+    }
+
+    if (!ExplainMatchResult(Not(INT32_MIN), arg.batteryCurrentMicroamps, result_listener)) {
+        *result_listener << " for batteryCurrentMicroamps.";
+        return false;
+    }
+
+    if (!ExplainMatchResult(InClosedRange(0, 100), arg.batteryLevel, result_listener)) {
+        *result_listener << " for batteryLevel.";
+        return false;
+    }
+
+    if (!ExplainMatchResult(IsValidEnum<BatteryHealth>(), arg.batteryHealth, result_listener)) {
+        *result_listener << " for batteryHealth.";
+        return false;
+    }
+
+    if (!ExplainMatchResult(IsValidEnum<BatteryStatus>(), arg.batteryStatus, result_listener)) {
+        *result_listener << " for batteryStatus.";
+        return false;
+    }
+
+    if (arg.batteryPresent) {
+        if (!ExplainMatchResult(Gt(0), arg.batteryChargeCounterUah, result_listener)) {
+            *result_listener << " for batteryChargeCounterUah when battery is present.";
+            return false;
+        }
+        if (!ExplainMatchResult(Not(BatteryStatus::UNKNOWN), arg.batteryStatus, result_listener)) {
+            *result_listener << " for batteryStatus when battery is present.";
+            return false;
+        }
+    }
+
+    if (!ExplainMatchResult(IsValidEnum<BatteryCapacityLevel>(), arg.batteryCapacityLevel,
+                            result_listener)) {
+        *result_listener << " for batteryCapacityLevel.";
+        return false;
+    }
+    if (!ExplainMatchResult(Ge(-1), arg.batteryChargeTimeToFullNowSeconds, result_listener)) {
+        *result_listener << " for batteryChargeTimeToFullNowSeconds.";
+        return false;
+    }
+
+    if (!ExplainMatchResult(
+                AnyOf(Eq(0), AllOf(Gt(kFullChargeDesignCapMinUah), Lt(kFullChargeDesignCapMaxUah))),
+                arg.batteryFullChargeDesignCapacityUah, result_listener)) {
+        *result_listener << " for batteryFullChargeDesignCapacityUah. It should be greater than "
+                            "100 mAh and less than 100,000 mAh, or 0 if unknown";
+        return false;
+    }
+
+    return true;
+}
+
+/*
+ * Tests the values returned by getHealthInfo() from interface IHealth.
+ */
+TEST_P(HealthAidl, getHealthInfo) {
+    HealthInfo value;
+    auto status = health->getHealthInfo(&value);
+    ASSERT_THAT(status, AnyOf(IsOk(), ExceptionIs(EX_UNSUPPORTED_OPERATION)));
+    if (!status.isOk()) return;
+    ASSERT_THAT(value, IsValidHealthInfo());
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HealthAidl);
+INSTANTIATE_TEST_SUITE_P(Health, HealthAidl,
+                         testing::ValuesIn(getAidlHalInstanceNames(IHealth::descriptor)),
+                         PrintInstanceNameToString);
+
+// For battery current tests, value may not be stable if the battery current has fluctuated.
+// Retry in a bit more time (with the following timeout) and consider the test successful if it
+// has succeed once.
+static constexpr auto gBatteryTestTimeout = 1min;
+static constexpr double gCurrentCompareFactor = 0.50;
+class BatteryTest : public HealthAidl {};
+
+// Tuple for all IHealth::get* API return values.
+template <typename T>
+struct HalResult {
+    std::shared_ptr<ScopedAStatus> result = std::make_shared<ScopedAStatus>();
+    T value;
+};
+
+// Needs to be called repeatedly within a period of time to ensure values are initialized.
+static AssertionResult IsBatteryCurrentSignCorrect(const HalResult<BatteryStatus>& status,
+                                                   const HalResult<int32_t>& current,
+                                                   bool acceptZeroCurrentAsUnknown) {
+    // getChargeStatus / getCurrentNow / getCurrentAverage / getHealthInfo already tested above.
+    // Here, just skip if not ok.
+    if (!status.result->isOk()) {
+        return AssertionSuccess() << "getChargeStatus / getHealthInfo returned "
+                                  << status.result->getDescription() << ", skipping";
+    }
+
+    if (!current.result->isOk()) {
+        return AssertionSuccess() << "getCurrentNow / getCurrentAverage returned "
+                                  << current.result->getDescription() << ", skipping";
+    }
+
+    return ::android::hardware::health::test_utils::IsBatteryCurrentSignCorrect(
+            status.value, current.value, acceptZeroCurrentAsUnknown,
+            [](BatteryStatus status) { return toString(status); });
+}
+
+static AssertionResult IsBatteryCurrentSimilar(const HalResult<BatteryStatus>& status,
+                                               const HalResult<int32_t>& current_now,
+                                               const HalResult<int32_t>& current_average) {
+    if (status.result->isOk() && status.value == BatteryStatus::FULL) {
+        // No reason to test on full battery because battery current load fluctuates.
+        return AssertionSuccess() << "Battery is full, skipping";
+    }
+
+    // getCurrentNow / getCurrentAverage / getHealthInfo already tested above. Here, just skip if
+    // not SUCCESS or value 0.
+    if (!current_now.result->isOk() || current_now.value == 0) {
+        return AssertionSuccess() << "getCurrentNow returned "
+                                  << current_now.result->getDescription() << " with value "
+                                  << current_now.value << ", skipping";
+    }
+
+    if (!current_average.result->isOk() || current_average.value == 0) {
+        return AssertionSuccess() << "getCurrentAverage returned "
+                                  << current_average.result->getDescription() << " with value "
+                                  << current_average.value << ", skipping";
+    }
+
+    return ::android::hardware::health::test_utils::IsBatteryCurrentSimilar(
+            current_now.value, current_average.value, gCurrentCompareFactor);
+}
+
+TEST_P(BatteryTest, InstantCurrentAgainstChargeStatusInHealthInfo) {
+    auto testOnce = [&]() -> AssertionResult {
+        HalResult<HealthInfo> health_info;
+        *health_info.result = health->getHealthInfo(&health_info.value);
+
+        return IsBatteryCurrentSignCorrect(
+                {health_info.result, health_info.value.batteryStatus},
+                {health_info.result, health_info.value.batteryCurrentMicroamps},
+                true /* accept zero current as unknown */);
+    };
+    EXPECT_TRUE(SucceedOnce(gBatteryTestTimeout, testOnce))
+            << "You may want to try again later when current_now becomes stable.";
+}
+
+TEST_P(BatteryTest, AverageCurrentAgainstChargeStatusInHealthInfo) {
+    auto testOnce = [&]() -> AssertionResult {
+        HalResult<HealthInfo> health_info;
+        *health_info.result = health->getHealthInfo(&health_info.value);
+        return IsBatteryCurrentSignCorrect(
+                {health_info.result, health_info.value.batteryStatus},
+                {health_info.result, health_info.value.batteryCurrentAverageMicroamps},
+                true /* accept zero current as unknown */);
+    };
+
+    EXPECT_TRUE(SucceedOnce(gBatteryTestTimeout, testOnce))
+            << "You may want to try again later when current_average becomes stable.";
+}
+
+TEST_P(BatteryTest, InstantCurrentAgainstAverageCurrentInHealthInfo) {
+    auto testOnce = [&]() -> AssertionResult {
+        HalResult<HealthInfo> health_info;
+        *health_info.result = health->getHealthInfo(&health_info.value);
+        return IsBatteryCurrentSimilar(
+                {health_info.result, health_info.value.batteryStatus},
+                {health_info.result, health_info.value.batteryCurrentMicroamps},
+                {health_info.result, health_info.value.batteryCurrentAverageMicroamps});
+    };
+
+    EXPECT_TRUE(SucceedOnce(gBatteryTestTimeout, testOnce))
+            << "You may want to try again later when current_now and current_average becomes "
+               "stable.";
+}
+
+TEST_P(BatteryTest, InstantCurrentAgainstChargeStatusFromHal) {
+    auto testOnce = [&]() -> AssertionResult {
+        HalResult<BatteryStatus> status;
+        *status.result = health->getChargeStatus(&status.value);
+        HalResult<int32_t> current_now;
+        *current_now.result = health->getCurrentNowMicroamps(&current_now.value);
+        return IsBatteryCurrentSignCorrect(status, current_now,
+                                           false /* accept zero current as unknown */);
+    };
+
+    EXPECT_TRUE(SucceedOnce(gBatteryTestTimeout, testOnce))
+            << "You may want to try again later when current_now becomes stable.";
+}
+
+TEST_P(BatteryTest, AverageCurrentAgainstChargeStatusFromHal) {
+    auto testOnce = [&]() -> AssertionResult {
+        HalResult<BatteryStatus> status;
+        *status.result = health->getChargeStatus(&status.value);
+        HalResult<int32_t> current_average;
+        *current_average.result = health->getCurrentAverageMicroamps(&current_average.value);
+        return IsBatteryCurrentSignCorrect(status, current_average,
+                                           false /* accept zero current as unknown */);
+    };
+
+    EXPECT_TRUE(SucceedOnce(gBatteryTestTimeout, testOnce))
+            << "You may want to try again later when current_average becomes stable.";
+}
+
+TEST_P(BatteryTest, InstantCurrentAgainstAverageCurrentFromHal) {
+    auto testOnce = [&]() -> AssertionResult {
+        HalResult<BatteryStatus> status;
+        *status.result = health->getChargeStatus(&status.value);
+        HalResult<int32_t> current_now;
+        *current_now.result = health->getCurrentNowMicroamps(&current_now.value);
+        HalResult<int32_t> current_average;
+        *current_average.result = health->getCurrentAverageMicroamps(&current_average.value);
+        return IsBatteryCurrentSimilar(status, current_now, current_average);
+    };
+
+    EXPECT_TRUE(SucceedOnce(gBatteryTestTimeout, testOnce))
+            << "You may want to try again later when current_average becomes stable.";
+}
+
+AssertionResult IsBatteryStatusCorrect(const HalResult<BatteryStatus>& status,
+                                       const HalResult<HealthInfo>& health_info) {
+    // getChargetStatus / getHealthInfo is already tested above. Here, just skip if not ok.
+    if (!health_info.result->isOk()) {
+        return AssertionSuccess() << "getHealthInfo returned "
+                                  << health_info.result->getDescription() << ", skipping";
+    }
+    if (!status.result->isOk()) {
+        return AssertionSuccess() << "getChargeStatus returned " << status.result->getDescription()
+                                  << ", skipping";
+    }
+    return ::android::hardware::health::test_utils::IsBatteryStatusCorrect(
+            status.value, health_info.value, [](BatteryStatus status) { return toString(status); });
+}
+
+TEST_P(BatteryTest, ConnectedAgainstStatusFromHal) {
+    auto testOnce = [&]() -> AssertionResult {
+        HalResult<BatteryStatus> status;
+        *status.result = health->getChargeStatus(&status.value);
+        HalResult<HealthInfo> health_info;
+        *health_info.result = health->getHealthInfo(&health_info.value);
+        return IsBatteryStatusCorrect(status, health_info);
+    };
+
+    EXPECT_TRUE(SucceedOnce(gBatteryTestTimeout, testOnce))
+            << "You may want to try again later when battery_status becomes stable.";
+}
+
+TEST_P(BatteryTest, ConnectedAgainstStatusInHealthInfo) {
+    auto testOnce = [&]() -> AssertionResult {
+        HalResult<HealthInfo> health_info;
+        *health_info.result = health->getHealthInfo(&health_info.value);
+        return IsBatteryStatusCorrect({health_info.result, health_info.value.batteryStatus},
+                                      health_info);
+    };
+
+    EXPECT_TRUE(SucceedOnce(gBatteryTestTimeout, testOnce))
+            << "You may want to try again later when getHealthInfo becomes stable.";
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BatteryTest);
+INSTANTIATE_TEST_SUITE_P(Health, BatteryTest,
+                         testing::ValuesIn(getAidlHalInstanceNames(IHealth::descriptor)),
+                         PrintInstanceNameToString);
+
+}  // namespace aidl::android::hardware::health
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    ABinderProcess_setThreadPoolMaxThreadCount(1);
+    ABinderProcess_startThreadPool();
+    return RUN_ALL_TESTS();
+}
diff --git a/health/storage/1.0/vts/functional/OWNERS b/health/storage/1.0/vts/functional/OWNERS
new file mode 100644
index 0000000..8f66979
--- /dev/null
+++ b/health/storage/1.0/vts/functional/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 30545
+elsk@google.com
+jaegeuk@google.com
diff --git a/health/storage/aidl/default/Android.bp b/health/storage/aidl/default/Android.bp
index 819b885..7cfabb0 100644
--- a/health/storage/aidl/default/Android.bp
+++ b/health/storage/aidl/default/Android.bp
@@ -29,7 +29,7 @@
     shared_libs: [
         "libbase",
         "libbinder_ndk",
-        "android.hardware.health.storage-V1-ndk_platform",
+        "android.hardware.health.storage-V1-ndk",
     ],
     static_libs: [
         "libfstab",
diff --git a/health/storage/aidl/default/main.cpp b/health/storage/aidl/default/main.cpp
index 186b64c..74e266f 100644
--- a/health/storage/aidl/default/main.cpp
+++ b/health/storage/aidl/default/main.cpp
@@ -24,14 +24,19 @@
 using std::string_literals::operator""s;
 
 int main() {
+    LOG(INFO) << "Health storage AIDL HAL starting...";
     ABinderProcess_setThreadPoolMaxThreadCount(0);
 
     // make a default storage service
     auto storage = ndk::SharedRefBase::make<Storage>();
     const std::string name = Storage::descriptor + "/default"s;
+    LOG(INFO) << "Health storage AIDL HAL registering...";
     CHECK_EQ(STATUS_OK,
              AServiceManager_registerLazyService(storage->asBinder().get(), name.c_str()));
 
+    LOG(INFO) << "Health storage AIDL HAL joining...";
     ABinderProcess_joinThreadPool();
+
+    LOG(ERROR) << "Health storage AIDL HAL join thread ends, exiting...";
     return EXIT_FAILURE;  // should not reach
 }
diff --git a/health/storage/aidl/vts/functional/Android.bp b/health/storage/aidl/vts/functional/Android.bp
index be3eac7..fe15170 100644
--- a/health/storage/aidl/vts/functional/Android.bp
+++ b/health/storage/aidl/vts/functional/Android.bp
@@ -34,7 +34,7 @@
         "libbinder_ndk",
     ],
     static_libs: [
-        "android.hardware.health.storage-V1-ndk_platform",
+        "android.hardware.health.storage-V1-ndk",
     ],
     header_libs: [
         "libhealth_storage_test_common_headers",
diff --git a/health/utils/libhealth2impl/BinderHealth.cpp b/health/utils/libhealth2impl/BinderHealth.cpp
index 625d0e0..8ec8962 100644
--- a/health/utils/libhealth2impl/BinderHealth.cpp
+++ b/health/utils/libhealth2impl/BinderHealth.cpp
@@ -35,10 +35,9 @@
 namespace V2_1 {
 namespace implementation {
 
-bool IsDeadObjectLogged(const Return<void>& ret) {
+bool IsDeadObject(const Return<void>& ret) {
     if (ret.isOk()) return false;
     if (ret.isDeadObject()) return true;
-    LOG(ERROR) << "Cannot call healthInfoChanged* on callback: " << ret.description();
     return false;
 }
 
@@ -77,7 +76,7 @@
             return;
         }
         auto ret = wrapped->Notify(health_info);
-        if (IsDeadObjectLogged(ret)) {
+        if (IsDeadObject(ret)) {
             // Remove callback reference.
             std::lock_guard<decltype(callbacks_lock_)> lock(callbacks_lock_);
             auto it = std::find_if(callbacks_.begin(), callbacks_.end(),
@@ -133,7 +132,7 @@
     std::unique_lock<decltype(callbacks_lock_)> lock(callbacks_lock_);
     for (auto it = callbacks_.begin(); it != callbacks_.end();) {
         auto ret = (*it)->Notify(health_info);
-        if (IsDeadObjectLogged(ret)) {
+        if (IsDeadObject(ret)) {
             it = callbacks_.erase(it);
         } else {
             ++it;
diff --git a/health/utils/libhealthloop/HealthLoop.cpp b/health/utils/libhealthloop/HealthLoop.cpp
index 3f4b5bc..4190769 100644
--- a/health/utils/libhealthloop/HealthLoop.cpp
+++ b/health/utils/libhealthloop/HealthLoop.cpp
@@ -40,8 +40,6 @@
 using namespace android;
 using namespace std::chrono_literals;
 
-#define POWER_SUPPLY_SUBSYSTEM "power_supply"
-
 namespace android {
 namespace hardware {
 namespace health {
@@ -143,7 +141,7 @@
     cp = msg;
 
     while (*cp) {
-        if (!strcmp(cp, "SUBSYSTEM=" POWER_SUPPLY_SUBSYSTEM)) {
+        if (!strcmp(cp, "SUBSYSTEM=power_supply")) {
             ScheduleBatteryUpdate();
             break;
         }
diff --git a/health/utils/libhealthloop/include/health/HealthLoop.h b/health/utils/libhealthloop/include/health/HealthLoop.h
index 693e6cb..54b2740 100644
--- a/health/utils/libhealthloop/include/health/HealthLoop.h
+++ b/health/utils/libhealthloop/include/health/HealthLoop.h
@@ -46,6 +46,12 @@
     // Init is called right after epollfd_ is initialized (so RegisterEvent
     // is allowed) but before other things are initialized (so SetChargerOnline
     // is not allowed.)
+    // The implementation of Init() should pull configuration from the
+    // underlying health HAL (via getHealthConfig()), and store it into
+    // |config|. The implementation may not initialize:
+    // - screen_on, because charger calls getScreenOn() from the HAL directly
+    // - ignorePowerSupplyNames, because it isn't used by any clients of the
+    // health HAL.
     virtual void Init(healthd_config* config) = 0;
     virtual void Heartbeat() = 0;
     virtual int PrepareToWait() = 0;
diff --git a/health/utils/libhealthshim/Android.bp b/health/utils/libhealthshim/Android.bp
new file mode 100644
index 0000000..3a1415f
--- /dev/null
+++ b/health/utils/libhealthshim/Android.bp
@@ -0,0 +1,83 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+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: "libhealthshim_defaults",
+    host_supported: true, // for testing
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    static_libs: [
+        "android.hardware.health-V1-ndk",
+        "android.hardware.health-translate-ndk",
+        "android.hardware.health@1.0",
+        "android.hardware.health@2.0",
+    ],
+    shared_libs: [
+        // These can be expected from the device or from host.
+        "libbase",
+        "libbinder_ndk",
+        "libcutils",
+        "libhidlbase",
+        "liblog",
+        "libutils",
+    ],
+}
+
+// Shim library that wraps a HIDL IHealth object into an AIDL IHealth object.
+cc_library_static {
+    name: "libhealthshim",
+    defaults: ["libhealthshim_defaults"],
+    recovery_available: true,
+    srcs: [
+        "shim.cpp",
+    ],
+    export_include_dirs: [
+        "include",
+    ],
+}
+
+cc_test {
+    name: "libhealthshim_test",
+    defaults: ["libhealthshim_defaults"],
+    static_libs: [
+        "libhealthshim",
+        "libgmock",
+    ],
+    tidy_timeout_srcs: [
+        "test.cpp",
+    ],
+    srcs: [
+        "test.cpp",
+    ],
+    test_suites: ["general-tests"],
+    test_options: {
+        unit_test: true,
+    },
+}
diff --git a/health/utils/libhealthshim/include/health-shim/shim.h b/health/utils/libhealthshim/include/health-shim/shim.h
new file mode 100644
index 0000000..f36fa5d
--- /dev/null
+++ b/health/utils/libhealthshim/include/health-shim/shim.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <map>
+
+#include <aidl/android/hardware/health/BnHealth.h>
+#include <android/hardware/health/2.0/IHealth.h>
+
+namespace aidl::android::hardware::health {
+
+// Shim that wraps HIDL IHealth with an AIDL BnHealth.
+// The wrapper always have isRemote() == false because it is BnHealth.
+class HealthShim : public BnHealth {
+    using HidlHealth = ::android::hardware::health::V2_0::IHealth;
+    using HidlHealthInfoCallback = ::android::hardware::health::V2_0::IHealthInfoCallback;
+
+  public:
+    explicit HealthShim(const ::android::sp<HidlHealth>& service);
+
+    ndk::ScopedAStatus registerCallback(
+            const std::shared_ptr<IHealthInfoCallback>& in_callback) override;
+    ndk::ScopedAStatus unregisterCallback(
+            const std::shared_ptr<IHealthInfoCallback>& in_callback) override;
+    ndk::ScopedAStatus update() override;
+    ndk::ScopedAStatus getChargeCounterUah(int32_t* _aidl_return) override;
+    ndk::ScopedAStatus getCurrentNowMicroamps(int32_t* _aidl_return) override;
+    ndk::ScopedAStatus getCurrentAverageMicroamps(int32_t* _aidl_return) override;
+    ndk::ScopedAStatus getCapacity(int32_t* _aidl_return) override;
+    ndk::ScopedAStatus getEnergyCounterNwh(int64_t* _aidl_return) override;
+    ndk::ScopedAStatus getChargeStatus(BatteryStatus* _aidl_return) override;
+    ndk::ScopedAStatus getStorageInfo(std::vector<StorageInfo>* _aidl_return) override;
+    ndk::ScopedAStatus getDiskStats(std::vector<DiskStats>* _aidl_return) override;
+    ndk::ScopedAStatus getHealthInfo(HealthInfo* _aidl_return) override;
+
+  private:
+    ::android::sp<HidlHealth> service_;
+    std::map<std::shared_ptr<IHealthInfoCallback>, ::android::sp<HidlHealthInfoCallback>>
+            callback_map_;
+};
+
+}  // namespace aidl::android::hardware::health
diff --git a/health/utils/libhealthshim/shim.cpp b/health/utils/libhealthshim/shim.cpp
new file mode 100644
index 0000000..1329679
--- /dev/null
+++ b/health/utils/libhealthshim/shim.cpp
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <android/hardware/health/translate-ndk.h>
+#include <health-shim/shim.h>
+
+using ::android::sp;
+using ::android::h2a::translate;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::health::V2_0::Result;
+using ::android::hardware::health::V2_0::toString;
+using ::ndk::ScopedAStatus;
+using HidlHealth = ::android::hardware::health::V2_0::IHealth;
+using HidlHealthInfoCallback = ::android::hardware::health::V2_0::IHealthInfoCallback;
+using HidlHealthInfo = ::android::hardware::health::V2_0::HealthInfo;
+
+namespace aidl::android::hardware::health {
+
+namespace {
+
+class HealthInfoCallbackShim : public HidlHealthInfoCallback {
+    using AidlHealthInfoCallback = ::aidl::android::hardware::health::IHealthInfoCallback;
+    using AidlHealthInfo = ::aidl::android::hardware::health::HealthInfo;
+
+  public:
+    explicit HealthInfoCallbackShim(const std::shared_ptr<AidlHealthInfoCallback>& impl)
+        : impl_(impl) {}
+    Return<void> healthInfoChanged(const HidlHealthInfo& info) override {
+        AidlHealthInfo aidl_info;
+        // translate() should always return true.
+        CHECK(translate(info, &aidl_info));
+        // This is a oneway function, so we can't (and shouldn't) check for errors.
+        (void)impl_->healthInfoChanged(aidl_info);
+        return Void();
+    }
+
+  private:
+    std::shared_ptr<AidlHealthInfoCallback> impl_;
+};
+
+ScopedAStatus ResultToStatus(Result result) {
+    switch (result) {
+        case Result::SUCCESS:
+            return ScopedAStatus::ok();
+        case Result::NOT_SUPPORTED:
+            return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+        case Result::UNKNOWN:
+            return ScopedAStatus::fromServiceSpecificError(IHealth::STATUS_UNKNOWN);
+        case Result::NOT_FOUND:
+            return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+        case Result::CALLBACK_DIED:
+            return ScopedAStatus::fromServiceSpecificError(IHealth::STATUS_CALLBACK_DIED);
+    }
+    return ScopedAStatus::fromServiceSpecificErrorWithMessage(
+            IHealth::STATUS_UNKNOWN, ("Unrecognized result value " + toString(result)).c_str());
+}
+
+template <typename T>
+ScopedAStatus ReturnAndResultToStatus(const Return<T>& ret, Result result) {
+    if (ret.isOk()) {
+        return ResultToStatus(result);
+    }
+    if (ret.isDeadObject()) {
+        return ScopedAStatus::fromStatus(STATUS_DEAD_OBJECT);
+    }
+    return ScopedAStatus::fromServiceSpecificErrorWithMessage(IHealth::STATUS_UNKNOWN,
+                                                              ret.description().c_str());
+}
+
+ScopedAStatus ReturnResultToStatus(const Return<Result>& return_result) {
+    return ReturnAndResultToStatus(return_result, return_result.isOk()
+                                                          ? static_cast<Result>(return_result)
+                                                          : Result::UNKNOWN);
+}
+
+}  // namespace
+
+HealthShim::HealthShim(const sp<HidlHealth>& service) : service_(service) {}
+
+ScopedAStatus HealthShim::registerCallback(
+        const std::shared_ptr<IHealthInfoCallback>& in_callback) {
+    sp<HidlHealthInfoCallback> shim(new HealthInfoCallbackShim(in_callback));
+    callback_map_.emplace(in_callback, shim);
+    return ReturnResultToStatus(service_->registerCallback(shim));
+}
+
+ScopedAStatus HealthShim::unregisterCallback(
+        const std::shared_ptr<IHealthInfoCallback>& in_callback) {
+    auto it = callback_map_.find(in_callback);
+    if (it == callback_map_.end()) {
+        return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    sp<HidlHealthInfoCallback> shim = it->second;
+    callback_map_.erase(it);
+    return ReturnResultToStatus(service_->unregisterCallback(shim));
+}
+
+ScopedAStatus HealthShim::update() {
+    return ReturnResultToStatus(service_->update());
+}
+
+ScopedAStatus HealthShim::getChargeCounterUah(int32_t* out) {
+    Result out_result = Result::UNKNOWN;
+    auto ret = service_->getChargeCounter([out, &out_result](auto result, auto value) {
+        out_result = result;
+        if (out_result != Result::SUCCESS) return;
+        *out = value;
+    });
+    return ReturnAndResultToStatus(ret, out_result);
+}
+
+ScopedAStatus HealthShim::getCurrentNowMicroamps(int32_t* out) {
+    Result out_result = Result::UNKNOWN;
+    auto ret = service_->getCurrentNow([out, &out_result](auto result, auto value) {
+        out_result = result;
+        if (out_result != Result::SUCCESS) return;
+        *out = value;
+    });
+    return ReturnAndResultToStatus(ret, out_result);
+}
+
+ScopedAStatus HealthShim::getCurrentAverageMicroamps(int32_t* out) {
+    Result out_result = Result::UNKNOWN;
+    auto ret = service_->getCurrentAverage([out, &out_result](auto result, auto value) {
+        out_result = result;
+        if (out_result != Result::SUCCESS) return;
+        *out = value;
+    });
+    return ReturnAndResultToStatus(ret, out_result);
+}
+
+ScopedAStatus HealthShim::getCapacity(int32_t* out) {
+    Result out_result = Result::UNKNOWN;
+    auto ret = service_->getCapacity([out, &out_result](auto result, auto value) {
+        out_result = result;
+        if (out_result != Result::SUCCESS) return;
+        *out = value;
+    });
+    return ReturnAndResultToStatus(ret, out_result);
+}
+
+ScopedAStatus HealthShim::getEnergyCounterNwh(int64_t* out) {
+    Result out_result = Result::UNKNOWN;
+    auto ret = service_->getEnergyCounter([out, &out_result](auto result, auto value) {
+        out_result = result;
+        if (out_result != Result::SUCCESS) return;
+        *out = value;
+    });
+    return ReturnAndResultToStatus(ret, out_result);
+}
+
+ScopedAStatus HealthShim::getChargeStatus(BatteryStatus* out) {
+    Result out_result = Result::UNKNOWN;
+    auto ret = service_->getChargeStatus([out, &out_result](auto result, auto value) {
+        out_result = result;
+        if (out_result != Result::SUCCESS) return;
+        *out = static_cast<BatteryStatus>(value);
+    });
+    return ReturnAndResultToStatus(ret, out_result);
+}
+
+ScopedAStatus HealthShim::getStorageInfo(std::vector<StorageInfo>* out) {
+    Result out_result = Result::UNKNOWN;
+    auto ret = service_->getStorageInfo([out, &out_result](auto result, const auto& value) {
+        out_result = result;
+        if (out_result != Result::SUCCESS) return;
+        out->clear();
+        out->reserve(value.size());
+        for (const auto& hidl_info : value) {
+            auto& aidl_info = out->emplace_back();
+            // translate() should always return true.
+            CHECK(translate(hidl_info, &aidl_info));
+        }
+    });
+    return ReturnAndResultToStatus(ret, out_result);
+}
+
+ScopedAStatus HealthShim::getDiskStats(std::vector<DiskStats>* out) {
+    Result out_result = Result::UNKNOWN;
+    auto ret = service_->getDiskStats([out, &out_result](auto result, const auto& value) {
+        out_result = result;
+        if (out_result != Result::SUCCESS) return;
+        out->clear();
+        out->reserve(value.size());
+        for (const auto& hidl_info : value) {
+            auto& aidl_info = out->emplace_back();
+            // translate() should always return true.
+            CHECK(translate(hidl_info, &aidl_info));
+        }
+    });
+    return ReturnAndResultToStatus(ret, out_result);
+}
+
+ScopedAStatus HealthShim::getHealthInfo(HealthInfo* out) {
+    Result out_result = Result::UNKNOWN;
+    auto ret = service_->getHealthInfo([out, &out_result](auto result, const auto& value) {
+        out_result = result;
+        if (out_result != Result::SUCCESS) return;
+        // translate() should always return true.
+        CHECK(translate(value, out));
+    });
+    return ReturnAndResultToStatus(ret, out_result);
+}
+
+}  // namespace aidl::android::hardware::health
diff --git a/health/utils/libhealthshim/test.cpp b/health/utils/libhealthshim/test.cpp
new file mode 100644
index 0000000..d1dfb8b
--- /dev/null
+++ b/health/utils/libhealthshim/test.cpp
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <health-shim/shim.h>
+
+#include <android/hardware/health/translate-ndk.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using HidlHealth = android::hardware::health::V2_0::IHealth;
+using HidlHealthInfoCallback = android::hardware::health::V2_0::IHealthInfoCallback;
+using HidlStorageInfo = android::hardware::health::V2_0::StorageInfo;
+using HidlDiskStats = android::hardware::health::V2_0::DiskStats;
+using HidlHealthInfo = android::hardware::health::V2_0::HealthInfo;
+using HidlBatteryStatus = android::hardware::health::V1_0::BatteryStatus;
+using android::sp;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::health::V2_0::Result;
+using ndk::SharedRefBase;
+using testing::Invoke;
+using testing::NiceMock;
+
+namespace aidl::android::hardware::health {
+MATCHER(IsOk, "") {
+    *result_listener << "status is " << arg.getDescription();
+    return arg.isOk();
+}
+
+MATCHER_P(ExceptionIs, exception_code, "") {
+    *result_listener << "status is " << arg.getDescription();
+    return arg.getExceptionCode() == exception_code;
+}
+
+class MockHidlHealth : public HidlHealth {
+  public:
+    MOCK_METHOD(Return<Result>, registerCallback, (const sp<HidlHealthInfoCallback>& callback),
+                (override));
+    MOCK_METHOD(Return<Result>, unregisterCallback, (const sp<HidlHealthInfoCallback>& callback),
+                (override));
+    MOCK_METHOD(Return<Result>, update, (), (override));
+    MOCK_METHOD(Return<void>, getChargeCounter, (getChargeCounter_cb _hidl_cb), (override));
+    MOCK_METHOD(Return<void>, getCurrentNow, (getCurrentNow_cb _hidl_cb), (override));
+    MOCK_METHOD(Return<void>, getCurrentAverage, (getCurrentAverage_cb _hidl_cb), (override));
+    MOCK_METHOD(Return<void>, getCapacity, (getCapacity_cb _hidl_cb), (override));
+    MOCK_METHOD(Return<void>, getEnergyCounter, (getEnergyCounter_cb _hidl_cb), (override));
+    MOCK_METHOD(Return<void>, getChargeStatus, (getChargeStatus_cb _hidl_cb), (override));
+    MOCK_METHOD(Return<void>, getStorageInfo, (getStorageInfo_cb _hidl_cb), (override));
+    MOCK_METHOD(Return<void>, getDiskStats, (getDiskStats_cb _hidl_cb), (override));
+    MOCK_METHOD(Return<void>, getHealthInfo, (getHealthInfo_cb _hidl_cb), (override));
+};
+
+class HealthShimTest : public ::testing::Test {
+  public:
+    void SetUp() override {
+        hidl = new NiceMock<MockHidlHealth>();
+        shim = SharedRefBase::make<HealthShim>(hidl);
+    }
+    sp<MockHidlHealth> hidl;
+    std::shared_ptr<IHealth> shim;
+};
+
+#define ADD_TEST(name, aidl_name, AidlValueType, hidl_value, not_supported_hidl_value) \
+    TEST_F(HealthShimTest, name) {                                                     \
+        ON_CALL(*hidl, name).WillByDefault(Invoke([](auto cb) {                        \
+            cb(Result::SUCCESS, hidl_value);                                           \
+            return Void();                                                             \
+        }));                                                                           \
+        AidlValueType value;                                                           \
+        ASSERT_THAT(shim->aidl_name(&value), IsOk());                                  \
+        ASSERT_EQ(value, static_cast<AidlValueType>(hidl_value));                      \
+    }                                                                                  \
+                                                                                       \
+    TEST_F(HealthShimTest, name##Unsupported) {                                        \
+        ON_CALL(*hidl, name).WillByDefault(Invoke([](auto cb) {                        \
+            cb(Result::NOT_SUPPORTED, not_supported_hidl_value);                       \
+            return Void();                                                             \
+        }));                                                                           \
+        AidlValueType value;                                                           \
+        ASSERT_THAT(shim->aidl_name(&value), ExceptionIs(EX_UNSUPPORTED_OPERATION));   \
+    }
+
+ADD_TEST(getChargeCounter, getChargeCounterUah, int32_t, 0xFEEDBEEF, 0)
+ADD_TEST(getCurrentNow, getCurrentNowMicroamps, int32_t, 0xC0FFEE, 0)
+ADD_TEST(getCurrentAverage, getCurrentAverageMicroamps, int32_t, 0xA2D401D, 0)
+ADD_TEST(getCapacity, getCapacity, int32_t, 77, 0)
+ADD_TEST(getEnergyCounter, getEnergyCounterNwh, int64_t, 0x1234567887654321, 0)
+ADD_TEST(getChargeStatus, getChargeStatus, BatteryStatus, HidlBatteryStatus::CHARGING,
+         HidlBatteryStatus::UNKNOWN)
+
+#undef ADD_TEST
+
+template <typename AidlValueType, typename HidlValueType>
+bool Translate(const HidlValueType& hidl_value, AidlValueType* aidl_value) {
+    return ::android::h2a::translate(hidl_value, aidl_value);
+}
+
+template <typename AidlValueType, typename HidlValueType>
+bool Translate(const std::vector<HidlValueType>& hidl_vec, std::vector<AidlValueType>* aidl_vec) {
+    aidl_vec->clear();
+    aidl_vec->reserve(hidl_vec.size());
+    for (const auto& hidl_value : hidl_vec) {
+        auto& aidl_value = aidl_vec->emplace_back();
+        if (!Translate(hidl_value, &aidl_value)) return false;
+    }
+    return true;
+}
+
+#define ADD_INFO_TEST(name, AidlValueType, hidl_value)                               \
+    TEST_F(HealthShimTest, name) {                                                   \
+        AidlValueType expected_aidl_value;                                           \
+        ASSERT_TRUE(Translate(hidl_value, &expected_aidl_value));                    \
+        ON_CALL(*hidl, name).WillByDefault(Invoke([&](auto cb) {                     \
+            cb(Result::SUCCESS, hidl_value);                                         \
+            return Void();                                                           \
+        }));                                                                         \
+        AidlValueType aidl_value;                                                    \
+        ASSERT_THAT(shim->name(&aidl_value), IsOk());                                \
+        ASSERT_EQ(aidl_value, expected_aidl_value);                                  \
+    }                                                                                \
+                                                                                     \
+    TEST_F(HealthShimTest, name##Unsupported) {                                      \
+        ON_CALL(*hidl, name).WillByDefault(Invoke([](auto cb) {                      \
+            cb(Result::NOT_SUPPORTED, {});                                           \
+            return Void();                                                           \
+        }));                                                                         \
+        AidlValueType aidl_value;                                                    \
+        ASSERT_THAT(shim->name(&aidl_value), ExceptionIs(EX_UNSUPPORTED_OPERATION)); \
+    }
+
+ADD_INFO_TEST(getStorageInfo, std::vector<StorageInfo>,
+              (std::vector<HidlStorageInfo>{{
+                      .lifetimeA = 15,
+                      .lifetimeB = 18,
+              }}))
+
+ADD_INFO_TEST(getDiskStats, std::vector<DiskStats>,
+              (std::vector<HidlDiskStats>{{
+                      .reads = 100,
+                      .writes = 200,
+              }}))
+
+ADD_INFO_TEST(getHealthInfo, HealthInfo,
+              (HidlHealthInfo{
+                      .batteryCurrentAverage = 999,
+              }))
+
+#undef ADD_INFO_TEST
+
+}  // namespace aidl::android::hardware::health
diff --git a/health/utils/libhealthtest/Android.bp b/health/utils/libhealthtest/Android.bp
new file mode 100644
index 0000000..0993cb6
--- /dev/null
+++ b/health/utils/libhealthtest/Android.bp
@@ -0,0 +1,38 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Utils library for VTS tests.
+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_headers {
+    name: "libhealthtest_headers",
+    static_libs: [
+        "libgmock",
+        "libgtest",
+    ],
+    export_static_lib_headers: [
+        "libgmock",
+        "libgtest",
+    ],
+    export_include_dirs: [
+        "include",
+    ],
+}
diff --git a/health/utils/libhealthtest/include/health-test/TestUtils.h b/health/utils/libhealthtest/include/health-test/TestUtils.h
new file mode 100644
index 0000000..e69c411
--- /dev/null
+++ b/health/utils/libhealthtest/include/health-test/TestUtils.h
@@ -0,0 +1,149 @@
+#pragma once
+
+#include <chrono>
+
+#include <gtest/gtest.h>
+
+namespace android::hardware::health::test_utils {
+
+using testing::AssertionFailure;
+using testing::AssertionResult;
+using testing::AssertionSuccess;
+using std::chrono_literals::operator""s;
+
+// Needs to be called repeatedly within a period of time to ensure values are initialized.
+template <typename BatteryStatusType, typename BatteryStatusToStringFn>
+inline AssertionResult IsBatteryCurrentSignCorrect(const BatteryStatusType& status, int32_t current,
+                                                   bool acceptZeroCurrentAsUnknown,
+                                                   const BatteryStatusToStringFn& toString) {
+    // For IHealth.getCurrentNow/Average, if current is not available, it is expected that
+    // the error code is NOT_SUPPORTED, which is checked above. Hence, zero current is
+    // not treated as unknown values.
+    // For IHealth.getHealthInfo, if current is not available, health_info.current_* == 0.
+    // Caller of this function provides current.result == Result::SUCCESS. Hence, just skip the
+    // check.
+    if (current == 0 && acceptZeroCurrentAsUnknown) {
+        return AssertionSuccess()
+               << "current is 0, which indicates the value may not be available. Skipping.";
+    }
+
+    switch (status) {
+        case BatteryStatusType::UNKNOWN:
+            if (current != 0) {
+                // BatteryStatus may be UNKNOWN initially with a non-zero current value, but
+                // after it is initialized, it should be known.
+                return AssertionFailure()
+                       << "BatteryStatus is UNKNOWN but current is not 0. Actual: " << current;
+            }
+            break;
+        case BatteryStatusType::CHARGING:
+            if (current <= 0) {
+                return AssertionFailure()
+                       << "BatteryStatus is CHARGING but current is not positive. Actual: "
+                       << current;
+            }
+            break;
+        case BatteryStatusType::NOT_CHARGING:
+            if (current > 0) {
+                return AssertionFailure() << "BatteryStatus is " << toString(status)
+                                          << " but current is positive. Actual: " << current;
+            }
+            break;
+        case BatteryStatusType::DISCHARGING:
+            if (current >= 0) {
+                return AssertionFailure() << "BatteryStatus is " << toString(status)
+                                          << " but current is not negative. Actual: " << current;
+            }
+            break;
+        case BatteryStatusType::FULL:
+            // Battery current may be positive or negative depending on the load.
+            break;
+        default:
+            return AssertionFailure() << "Unknown BatteryStatus " << toString(status);
+    }
+
+    return AssertionSuccess() << "BatteryStatus is " << toString(status)
+                              << " and current has the correct sign: " << current;
+}
+
+inline AssertionResult IsValueSimilar(int32_t dividend, int32_t divisor, double factor) {
+    auto difference = abs(dividend - divisor);
+    if (difference > factor * abs(divisor)) {
+        return AssertionFailure() << dividend << " and " << divisor
+                                  << " are not similar (factor = " << factor << ")";
+    }
+    return AssertionSuccess() << dividend << " and " << divisor
+                              << " are similar (factor = " << factor << ")";
+}
+
+inline AssertionResult IsBatteryCurrentSimilar(int32_t currentNow, int32_t currentAverage,
+                                               double currentCompareFactor) {
+    // Check that the two values are similar. Note that the two tests uses a different
+    // divisor to ensure that they are actually pretty similar. For example,
+    // IsValueSimilar(5,10,0.4) returns true, but IsValueSimlar(10,5,0.4) returns false.
+    auto res = IsValueSimilar(currentNow, currentAverage, currentCompareFactor)
+               << " for now vs. average. Check units.";
+    if (!res) return res;
+    res = IsValueSimilar(currentAverage, currentNow, currentCompareFactor)
+          << " for average vs. now. Check units.";
+    if (!res) return res;
+    return AssertionSuccess() << "currentNow = " << currentNow
+                              << " and currentAverage = " << currentAverage
+                              << " are considered similar.";
+}
+
+// Test that f() returns AssertionSuccess() once in a given period of time.
+template <typename Duration, typename Function>
+inline AssertionResult SucceedOnce(Duration d, Function f) {
+    AssertionResult result = AssertionFailure() << "Function is never evaluated.";
+    auto end = std::chrono::system_clock::now() + d;
+    while (std::chrono::system_clock::now() <= end) {
+        result = f();
+        if (result) {
+            return result;
+        }
+        std::this_thread::sleep_for(2s);
+    }
+    return result;
+}
+
+template <typename BatteryStatusType, typename BatteryInfoType, typename BatteryStatusToStringFn>
+AssertionResult IsBatteryStatusCorrect(const BatteryStatusType& status,
+                                       const BatteryInfoType& batteryInfo,
+                                       const BatteryStatusToStringFn& toString) {
+    bool isConnected = batteryInfo.chargerAcOnline || batteryInfo.chargerUsbOnline ||
+                       batteryInfo.chargerWirelessOnline;
+
+    std::stringstream message;
+    message << "BatteryStatus is " << toString(status) << " and " << (isConnected ? "" : "no ")
+            << "power source is connected: ac=" << batteryInfo.chargerAcOnline
+            << ", usb=" << batteryInfo.chargerUsbOnline
+            << ", wireless=" << batteryInfo.chargerWirelessOnline;
+
+    switch (status) {
+        case BatteryStatusType::UNKNOWN: {
+            // Don't enforce anything on isConnected on unknown battery status.
+            // Battery-less devices must report UNKNOWN battery status, but may report true
+            // or false on isConnected.
+        } break;
+        case BatteryStatusType::CHARGING:
+        case BatteryStatusType::NOT_CHARGING:
+        case BatteryStatusType::FULL: {
+            if (!isConnected) {
+                return AssertionFailure() << message.str();
+            }
+        } break;
+        case BatteryStatusType::DISCHARGING: {
+            if (isConnected) {
+                return AssertionFailure() << message.str();
+            }
+        } break;
+        default: {
+            return AssertionFailure() << "Unknown battery status value " << toString(status);
+        } break;
+    }
+
+    return AssertionSuccess() << message.str();
+}
+
+}  // namespace android::hardware::health::test_utils
diff --git a/identity/aidl/Android.bp b/identity/aidl/Android.bp
index dad3b8d..e3b8191 100644
--- a/identity/aidl/Android.bp
+++ b/identity/aidl/Android.bp
@@ -15,6 +15,7 @@
     ],
     imports: [
         "android.hardware.keymaster",
+        "android.hardware.security.keymint",
     ],
     stability: "vintf",
     backend: {
@@ -25,6 +26,7 @@
             vndk: {
                 enabled: true,
             },
+            apps_enabled: false,
         },
     },
     versions: [
diff --git a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/Certificate.aidl b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/Certificate.aidl
index d8a8128..83e1797 100644
--- a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/Certificate.aidl
+++ b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/Certificate.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/CipherSuite.aidl b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/CipherSuite.aidl
index 2685525..e6ec04e 100644
--- a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/CipherSuite.aidl
+++ b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/CipherSuite.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/HardwareInformation.aidl b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/HardwareInformation.aidl
index f8d5a9e..9b96ea8 100644
--- a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/HardwareInformation.aidl
+++ b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/HardwareInformation.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -38,4 +39,5 @@
   int dataChunkSize;
   boolean isDirectAccess;
   @utf8InCpp String[] supportedDocTypes;
+  boolean isRemoteKeyProvisioningSupported = false;
 }
diff --git a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IIdentityCredential.aidl b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IIdentityCredential.aidl
index 3224e4b..5065641 100644
--- a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IIdentityCredential.aidl
+++ b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IIdentityCredential.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IIdentityCredentialStore.aidl b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IIdentityCredentialStore.aidl
index c6fb3c8..31ca8b1 100644
--- a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IIdentityCredentialStore.aidl
+++ b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IIdentityCredentialStore.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -36,6 +37,8 @@
   android.hardware.identity.HardwareInformation getHardwareInformation();
   android.hardware.identity.IWritableIdentityCredential createCredential(in @utf8InCpp String docType, in boolean testCredential);
   android.hardware.identity.IIdentityCredential getCredential(in android.hardware.identity.CipherSuite cipherSuite, in byte[] credentialData);
+  android.hardware.identity.IPresentationSession createPresentationSession(in android.hardware.identity.CipherSuite cipherSuite);
+  android.hardware.security.keymint.IRemotelyProvisionedComponent getRemotelyProvisionedComponent();
   const int STATUS_OK = 0;
   const int STATUS_FAILED = 1;
   const int STATUS_CIPHER_SUITE_NOT_SUPPORTED = 2;
diff --git a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IPresentationSession.aidl b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IPresentationSession.aidl
new file mode 100644
index 0000000..705dc29
--- /dev/null
+++ b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IPresentationSession.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.identity;
+@VintfStability
+interface IPresentationSession {
+  byte[] getEphemeralKeyPair();
+  long getAuthChallenge();
+  void setReaderEphemeralPublicKey(in byte[] publicKey);
+  void setSessionTranscript(in byte[] sessionTranscript);
+  android.hardware.identity.IIdentityCredential getCredential(in byte[] credentialData);
+}
diff --git a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IWritableIdentityCredential.aidl b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IWritableIdentityCredential.aidl
index 19a29ec..5377349 100644
--- a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IWritableIdentityCredential.aidl
+++ b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IWritableIdentityCredential.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -40,4 +41,5 @@
   byte[] addEntryValue(in byte[] content);
   @SuppressWarnings(value={"out-array"}) void finishAddingEntries(out byte[] credentialData, out byte[] proofOfProvisioningSignature);
   void setExpectedProofOfProvisioningSize(in int expectedProofOfProvisioningSize);
+  void setRemotelyProvisionedAttestationKey(in byte[] attestationKeyBlob, in byte[] attestationCertificate);
 }
diff --git a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/RequestDataItem.aidl b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/RequestDataItem.aidl
index c9c2b9f..cec8e0c 100644
--- a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/RequestDataItem.aidl
+++ b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/RequestDataItem.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/RequestNamespace.aidl b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/RequestNamespace.aidl
index aaf1e20..05b9ec2 100644
--- a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/RequestNamespace.aidl
+++ b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/RequestNamespace.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/SecureAccessControlProfile.aidl b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/SecureAccessControlProfile.aidl
index 695fb3f..2003594 100644
--- a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/SecureAccessControlProfile.aidl
+++ b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/SecureAccessControlProfile.aidl
@@ -12,7 +12,8 @@
  * WITHOUT 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/identity/aidl/android/hardware/identity/HardwareInformation.aidl b/identity/aidl/android/hardware/identity/HardwareInformation.aidl
index d67739d..acd13b6 100644
--- a/identity/aidl/android/hardware/identity/HardwareInformation.aidl
+++ b/identity/aidl/android/hardware/identity/HardwareInformation.aidl
@@ -51,4 +51,19 @@
      *
      */
     @utf8InCpp String[] supportedDocTypes;
+
+    /**
+     * isRemoteKeyProvisioningSupported indicates whether or not the underlying implementation
+     * supports a remotely provisioned key for attestation or not. If this field is false, then
+     * the implementation only uses a factory-installed, fixed attestation key. If this field is
+     * true, then an IRemotelyProvisionedComponent is associated with the IIdentityCredentialStore,
+     * and a remotely provisioned key blob may be provided for credential key attestation.
+     *
+     * Note that remote provisioning is not required, even when it is supported. Implementations
+     * MUST use a factory-installed attestation key as a fallback for when there are no
+     * remotely provisioned keys available. This behavior mirrors keystore key attestation.
+     *
+     * This field was added in API version 4.
+     */
+    boolean isRemoteKeyProvisioningSupported = false;
 }
diff --git a/identity/aidl/android/hardware/identity/IIdentityCredential.aidl b/identity/aidl/android/hardware/identity/IIdentityCredential.aidl
index 8ae293b..82b0a83 100644
--- a/identity/aidl/android/hardware/identity/IIdentityCredential.aidl
+++ b/identity/aidl/android/hardware/identity/IIdentityCredential.aidl
@@ -17,9 +17,9 @@
 package android.hardware.identity;
 
 import android.hardware.identity.Certificate;
+import android.hardware.identity.IWritableIdentityCredential;
 import android.hardware.identity.RequestNamespace;
 import android.hardware.identity.SecureAccessControlProfile;
-import android.hardware.identity.IWritableIdentityCredential;
 import android.hardware.keymaster.HardwareAuthToken;
 import android.hardware.keymaster.VerificationToken;
 
@@ -44,6 +44,9 @@
      * This method was deprecated in API version 3 because there's no challenge so freshness
      * can't be checked. Use deleteCredentalWithChallenge() instead.
      *
+     * If the method is called on an instance obtained via IPresentationSession.getCredential(),
+     * STATUS_FAILED must be returned.
+     *
      * @return a COSE_Sign1 signature described above
      * @deprecated use deleteCredentalWithChallenge() instead.
      */
@@ -60,6 +63,9 @@
      * This method may only be called once per instance. If called more than once, STATUS_FAILED
      * will be returned.
      *
+     * If the method is called on an instance obtained via IPresentationSession.getCredential(),
+     * STATUS_FAILED must be returned.
+     *
      * @return the private key, in DER format as specified in RFC 5915.
      */
     byte[] createEphemeralKeyPair();
@@ -70,6 +76,9 @@
      * This method may only be called once per instance. If called more than once, STATUS_FAILED
      * will be returned.
      *
+     * If the method is called on an instance obtained via IPresentationSession.getCredential(),
+     * STATUS_FAILED must be returned.
+     *
      * @param publicKey contains the reader's ephemeral public key, in uncompressed
      *        form (e.g. 0x04 || X || Y).
      */
@@ -83,6 +92,9 @@
      * This method may only be called once per instance. If called more than once, STATUS_FAILED
      * will be returned. If user authentication is not needed, this method may not be called.
      *
+     * If the method is called on an instance obtained via IPresentationSession.getCredential(),
+     * STATUS_FAILED must be returned.
+     *
      * @return challenge, a non-zero number.
      */
     long createAuthChallenge();
@@ -371,6 +383,9 @@
      * This CBOR enables an issuer to determine the exact state of the credential it
      * returns issuer-signed data for.
      *
+     * If the method is called on an instance obtained via IPresentationSession.getCredential(),
+     * STATUS_FAILED must be returned.
+     *
      * @param out signingKeyBlob contains an AES-GCM-ENC(storageKey, R, signingKey, docType)
      *     where signingKey is an EC private key in uncompressed form. That is, the returned
      *     blob is an encrypted copy of the newly-generated private signing key.
@@ -420,8 +435,12 @@
      *
      * This method was introduced in API version 3.
      *
-     * @param challenge a challenge set by the issuer to ensure freshness. Maximum size is 32 bytes
-     *     and it may be empty. Fails with STATUS_INVALID_DATA if bigger than 32 bytes.
+     * If the method is called on an instance obtained via IPresentationSession.getCredential(),
+     * STATUS_FAILED must be returned.
+     *
+     * @param challenge a challenge set by the issuer to ensure freshness. Implementations must
+     *   support challenges that are at least 32 bytes. Fails with STATUS_INVALID_DATA if bigger
+     *   than 32 bytes.
      * @return a COSE_Sign1 signature described above.
      */
     byte[] deleteCredentialWithChallenge(in byte[] challenge);
@@ -442,8 +461,12 @@
      *
      * This method was introduced in API version 3.
      *
-     * @param challenge a challenge set by the issuer to ensure freshness. Maximum size is 32 bytes
-     *     and it may be empty. Fails with STATUS_INVALID_DATA if bigger than 32 bytes.
+     * If the method is called on an instance obtained via IPresentationSession.getCredential(),
+     * STATUS_FAILED must be returned.
+     *
+     * @param challenge a challenge set by the issuer to ensure freshness. Implementations must
+     *   support challenges that are at least 32 bytes. Fails with STATUS_INVALID_DATA if bigger
+     *   than 32 bytes.
      * @return a COSE_Sign1 signature described above.
      */
     byte[] proveOwnership(in byte[] challenge);
@@ -456,6 +479,9 @@
      *
      * This method was introduced in API version 3.
      *
+     * If the method is called on an instance obtained via IPresentationSession.getCredential(),
+     * STATUS_FAILED must be returned.
+     *
      * @return an IWritableIdentityCredential
      */
     IWritableIdentityCredential updateCredential();
diff --git a/identity/aidl/android/hardware/identity/IIdentityCredentialStore.aidl b/identity/aidl/android/hardware/identity/IIdentityCredentialStore.aidl
index 638be79..d3e4da0 100644
--- a/identity/aidl/android/hardware/identity/IIdentityCredentialStore.aidl
+++ b/identity/aidl/android/hardware/identity/IIdentityCredentialStore.aidl
@@ -16,10 +16,12 @@
 
 package android.hardware.identity;
 
-import android.hardware.identity.IIdentityCredential;
-import android.hardware.identity.IWritableIdentityCredential;
-import android.hardware.identity.HardwareInformation;
 import android.hardware.identity.CipherSuite;
+import android.hardware.identity.HardwareInformation;
+import android.hardware.identity.IIdentityCredential;
+import android.hardware.identity.IPresentationSession;
+import android.hardware.identity.IWritableIdentityCredential;
+import android.hardware.security.keymint.IRemotelyProvisionedComponent;
 
 /**
  * IIdentityCredentialStore provides an interface to a secure store for user identity documents.
@@ -105,7 +107,7 @@
  * STATUS_* integers defined in this interface. Each method states which status can be returned
  * and under which circumstances.
  *
- * The API described here is API version 3 which corresponds to feature version 202101
+ * The API described here is API version 4 which corresponds to feature version 202201
  * of the android.security.identity Framework API. An XML file declaring the feature
  * android.hardware.identity_credential (or android.hardware.identity_credential.direct_access
  * if implementing the Direct Access HAL) should be included declaring this feature version.
@@ -214,16 +216,16 @@
      * @return an IWritableIdentityCredential interface that provides operations to
      *     provision a credential.
      */
-    IWritableIdentityCredential createCredential(in @utf8InCpp String docType,
-                                                 in boolean testCredential);
+    IWritableIdentityCredential createCredential(
+            in @utf8InCpp String docType, in boolean testCredential);
 
     /**
      * getCredential retrieves an IIdentityCredential interface which allows use of a stored
      * Credential.
      *
-     * The cipher suite used to communicate with the remote verifier must also be specified. Currently
-     * only a single cipher-suite is supported. Support for other cipher suites may be added in a
-     * future version of this HAL.
+     * The cipher suite used to communicate with the remote verifier must also be specified.
+     * Currently only a single cipher-suite is supported. Support for other cipher suites may be
+     * added in a future version of this HAL.
      *
      * This method fails with STATUS_INVALID_DATA if the passed in credentialData cannot be
      * decoded or decrypted.
@@ -241,4 +243,44 @@
      * @return an IIdentityCredential interface that provides operations on the Credential.
      */
     IIdentityCredential getCredential(in CipherSuite cipherSuite, in byte[] credentialData);
+
+    /**
+     * createPresentationSession creates IPresentationSession interface which can be used to
+     * present one or more credentials to a remote verifier device.
+     *
+     * The cipher suite used to communicate with the remote verifier must be specified. Currently
+     * only a single cipher-suite is supported. Support for other cipher suites may be added in a
+     * future version of this HAL. If the requested cipher suite is not support the call fails
+     * with STATUS_CIPHER_SUITE_NOT_SUPPORTED.
+     *
+     * In this version of the HAL, implementations are only required to support a single session
+     * being active. In a future version, implementations may be required to support multiple
+     * presentation sessions being active at the same time.
+     *
+     * This method was introduced in API version 4.
+     *
+     * @param cipherSuite The cipher suite to use.
+     *
+     * @return an IPresentationSession interface.
+     */
+    IPresentationSession createPresentationSession(in CipherSuite cipherSuite);
+
+    /**
+     * Fetch the IRemotelyProvisionedComponent that is used to generate attestation keys for
+     * remote provisionining. Keys generated by this component are to be certified by a remote
+     * provisionined authority, then used to attest to credential keys via
+     * IWritableIdentityCredential.setRemotelyProvisionedAttestationKey.
+     *
+     * Support for this method is indicated by HardwareInformation. If the
+     * |isRemoteKeyProvisioningSupported| field is false, this method will fail with
+     * EX_UNSUPPORTED_OPERATION.
+     *
+     * This method was added in API version 4.
+     *
+     * @see
+     *         android.hardware.identity.IWritableIdentityCredential#setRemotelyProvisionedAttestationKey
+     *
+     * @return an IRemotelyProvisionedComponent that is used to generate attestation keys.
+     */
+    IRemotelyProvisionedComponent getRemotelyProvisionedComponent();
 }
diff --git a/identity/aidl/android/hardware/identity/IPresentationSession.aidl b/identity/aidl/android/hardware/identity/IPresentationSession.aidl
new file mode 100644
index 0000000..b0449f0
--- /dev/null
+++ b/identity/aidl/android/hardware/identity/IPresentationSession.aidl
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.identity;
+
+import android.hardware.identity.CipherSuite;
+import android.hardware.identity.IIdentityCredential;
+
+/**
+ * An interface to present multiple credentials in the same session.
+ *
+ * This interface was introduced in API version 4.
+ *
+ */
+@VintfStability
+interface IPresentationSession {
+    /**
+     * Gets the ephemeral EC key pair to be used in establishing a secure session with a reader.
+     * This method returns the private key so the caller can perform an ECDH key agreement operation
+     * with the reader.  The reason for generating the key pair in the secure environment is so that
+     * the secure environment knows what public key to expect to find in the session transcript
+     * when presenting credentials.
+     *
+     * The generated key matches the selected cipher suite of the presentation session (e.g. EC
+     * key using the P-256 curve).
+     *
+     * @return the private key, in DER format as specified in RFC 5915.
+     */
+    byte[] getEphemeralKeyPair();
+
+    /**
+     * Gets the challenge value to be used for proving successful user authentication. This
+     * is to be included in the authToken passed to the IIdentityCredential.startRetrieval()
+     * method and the verificationToken passed to the IIdentityCredential.setVerificationToken()
+     * method.
+     *
+     * @return challenge, a non-zero number.
+     */
+    long getAuthChallenge();
+
+    /**
+     * Sets the public part of the reader's ephemeral key pair to be used to complete
+     * an ECDH key agreement for the session.
+     *
+     * The curve of the key must match the curve for the key returned by getEphemeralKeyPair().
+     *
+     * This method may only be called once per instance. If called more than once, STATUS_FAILED
+     * must be returned.
+     *
+     * @param publicKey contains the reader's ephemeral public key, in uncompressed
+     *        form (e.g. 0x04 || X || Y).
+     */
+    void setReaderEphemeralPublicKey(in byte[] publicKey);
+
+    /**
+     * Sets the session transcript for the session.
+     *
+     * This can be empty but if it's non-empty it must be valid CBOR.
+     *
+     * This method may only be called once per instance. If called more than once, STATUS_FAILED
+     * must be returned.
+     *
+     * @param sessionTrancsript the session transcript.
+     */
+    void setSessionTranscript(in byte[] sessionTranscript);
+
+    /**
+     * getCredential() retrieves an IIdentityCredential interface for presentation in the
+     * current presentation session.
+     *
+     * On the returned instance only the methods startRetrieval(), startRetrieveEntryValue(),
+     * retrieveEntryValue(), finishRetrieval(), setRequestedNamespaces(), setVerificationToken()
+     * may be called. Other methods will fail with STATUS_FAILED.
+     *
+     * The implementation is expected to get the session transcript, ephemeral key, reader
+     * ephemeral key, and auth challenge from this instance.
+     *
+     * @param credentialData is a CBOR-encoded structure containing metadata about the credential
+     *     and an encrypted byte array that contains data used to secure the credential.  See the
+     *     return argument of the same name in IWritableIdentityCredential.finishAddingEntries().
+     *
+     *     Note that the format of credentialData may depend on the feature version.
+     *     Implementations must support credentialData created by an earlier feature version.
+     *
+     * @return an IIdentityCredential interface that provides operations on the Credential.
+     */
+    IIdentityCredential getCredential(in byte[] credentialData);
+}
diff --git a/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl b/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl
index 22bcf61..1c80cbb 100644
--- a/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl
+++ b/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl
@@ -127,11 +127,13 @@
      *     https://developer.android.com/training/articles/security-key-attestation#certificate_schema_attestationid
      *
      * @param attestationChallenge a challenge set by the issuer to ensure freshness. If
-     *    this is empty, the call fails with STATUS_INVALID_DATA.
+     *    this is empty, the call fails with STATUS_INVALID_DATA. Implementations must
+     *    support challenges of at least 32 bytes.
      *
      * @return the X.509 certificate chain for the credentialKey
      */
-    Certificate[] getAttestationCertificate(in byte[] attestationApplicationId, in byte[] attestationChallenge);
+    Certificate[] getAttestationCertificate(
+            in byte[] attestationApplicationId, in byte[] attestationChallenge);
 
     /**
      * Start the personalization process.
@@ -183,11 +185,11 @@
      *     in the secure environment. If this requirement is not met the call fails with
      *     STATUS_INVALID_DATA.
      *
-     * @return a structure with the passed-in data and MAC created with storageKey for authenticating
-     *     the data at a later point in time.
+     * @return a structure with the passed-in data and MAC created with storageKey for
+     *     authenticating the data at a later point in time.
      */
     SecureAccessControlProfile addAccessControlProfile(in int id, in Certificate readerCertificate,
-        in boolean userAuthenticationRequired, in long timeoutMillis, in long secureUserId);
+            in boolean userAuthenticationRequired, in long timeoutMillis, in long secureUserId);
 
     /**
      * Begins the process of adding an entry to the credential.  All access control profiles must be
@@ -209,7 +211,7 @@
      *     is not met this method fails with STATUS_INVALID_DATA.
      */
     void beginAddEntry(in int[] accessControlProfileIds, in @utf8InCpp String nameSpace,
-        in @utf8InCpp String name, in int entrySize);
+            in @utf8InCpp String name, in int entrySize);
 
     /**
      * Continues the process of adding an entry, providing a value or part of a value.
@@ -221,8 +223,8 @@
      * chunk sizes must equal the value of the beginAddEntry() entrySize argument. If this
      * requirement is not met the call fails with STATUS_INVALID_DATA.
      *
-     * @param content is the entry value, encoded as CBOR. In the case the content exceeds gcmChunkSize,
-     *     this may be partial content up to gcmChunkSize bytes long.
+     * @param content is the entry value, encoded as CBOR. In the case the content exceeds
+     *     gcmChunkSize, this may be partial content up to gcmChunkSize bytes long.
      *
      * @return the encrypted and MACed content.  For directly-available credentials the contents are
      *     implementation-defined. For other credentials, the result contains
@@ -321,8 +323,7 @@
      *          }
      */
     @SuppressWarnings(value={"out-array"})
-    void finishAddingEntries(out byte[] credentialData,
-        out byte[] proofOfProvisioningSignature);
+    void finishAddingEntries(out byte[] credentialData, out byte[] proofOfProvisioningSignature);
 
     /**
      * Sets the expected size of the ProofOfProvisioning returned by finishAddingEntries(). This
@@ -336,4 +337,35 @@
      */
     void setExpectedProofOfProvisioningSize(in int expectedProofOfProvisioningSize);
 
+    /**
+     * Sets the attestation key used to sign the credentialKey certificate. This method is used to
+     * support remotely provisioned attestation keys, removing the credential's dependency on any
+     * factory-provisioned attestation key.
+     *
+     * This method must be called before getAttestationCertificate. After this method is called,
+     * the certificate chain returned by getAttestationCertificate will contain a leaf certificate
+     * signed by attestationKeyBlob and the chain in attestationCertificate will make up the rest
+     * of the returned chain.
+     *
+     * Returns EX_UNSUPPORTED_FUNCTION if remote provisioning is not supported
+     * (see IIdentityCredentialStore.getHardwareInformation()).
+     *
+     * This method was added in API version 4.
+     *
+     * @param attestationKeyBlob is a key blob generated by the IRemotelyProvisionedComponent that
+     *     is returned by ICredentialStore.getRemotelyProvisionedComponent. The format is vendor-
+     *     specified, and matches the key blob returned by IKeyMintDevice.generateKey.
+     *
+     * @param attestationCertificate contains the X.509 certificate chain that certifies the
+     *     attestationKeyBlob. This certificate is expected to have been remotely provisioned
+     *     by a trusted authority. This parameter must contain a concatenated chain of DER-encoded
+     *     X.509 certificates. The certificates must be ordered such that the attestation key
+     *     certificate is first (starting at byte 0). The issuer certificate for the attestation
+     *     certificate immediately follows, continuing this chain to the final, root certificate.
+     *
+     * @see getAttestationCertificate
+     * @see android.hardware.identity.ICredentialStore#getRemotelyProvisionedComponent
+     */
+    void setRemotelyProvisionedAttestationKey(
+            in byte[] attestationKeyBlob, in byte[] attestationCertificate);
 }
diff --git a/identity/aidl/default/Android.bp b/identity/aidl/default/Android.bp
index 28c4893..32b3543 100644
--- a/identity/aidl/default/Android.bp
+++ b/identity/aidl/default/Android.bp
@@ -13,6 +13,7 @@
     srcs: [
         "common/IdentityCredential.cpp",
         "common/IdentityCredentialStore.cpp",
+        "common/PresentationSession.cpp",
         "common/WritableIdentityCredential.cpp",
     ],
     export_include_dirs: [
@@ -39,8 +40,9 @@
         "libsoft_attestation_cert",
         "libpuresoftkeymasterdevice",
         "android.hardware.identity-support-lib",
-        "android.hardware.identity-V3-ndk_platform",
-        "android.hardware.keymaster-V3-ndk_platform",
+        "android.hardware.identity-V4-ndk",
+        "android.hardware.keymaster-V4-ndk",
+        "android.hardware.security.keymint-V2-ndk",
     ],
 }
 
@@ -49,6 +51,7 @@
     vendor_available: true,
     srcs: [
         "libeic/EicCbor.c",
+        "libeic/EicSession.c",
         "libeic/EicPresentation.c",
         "libeic/EicProvisioning.c",
         "EicOpsImpl.cc",
@@ -79,6 +82,9 @@
     init_rc: ["identity-default.rc"],
     vintf_fragments: ["identity-default.xml"],
     vendor: true,
+    defaults: [
+        "keymint_use_latest_hal_aidl_ndk_static",
+    ],
     cflags: [
         "-Wall",
         "-Wextra",
@@ -100,8 +106,8 @@
         "libsoft_attestation_cert",
         "libpuresoftkeymasterdevice",
         "android.hardware.identity-support-lib",
-        "android.hardware.identity-V3-ndk_platform",
-        "android.hardware.keymaster-V3-ndk_platform",
+        "android.hardware.identity-V4-ndk",
+        "android.hardware.keymaster-V4-ndk",
         "android.hardware.identity-libeic-hal-common",
         "android.hardware.identity-libeic-library",
     ],
@@ -127,7 +133,7 @@
         "-DEIC_DEBUG",
     ],
     local_include_dirs: [
-         "common",
+        "common",
     ],
     shared_libs: [
         "liblog",
diff --git a/identity/aidl/default/EicOpsImpl.cc b/identity/aidl/default/EicOpsImpl.cc
index 8ec4cc9..3fd9f1d 100644
--- a/identity/aidl/default/EicOpsImpl.cc
+++ b/identity/aidl/default/EicOpsImpl.cc
@@ -20,9 +20,13 @@
 #include <tuple>
 #include <vector>
 
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include <string.h>
+
 #include <android-base/logging.h>
 #include <android-base/stringprintf.h>
-#include <string.h>
 
 #include <android/hardware/identity/support/IdentityCredentialSupport.h>
 
@@ -63,6 +67,11 @@
     return strlen(s);
 }
 
+void* eicMemMem(const uint8_t* haystack, size_t haystackLen, const uint8_t* needle,
+                size_t needleLen) {
+    return memmem(haystack, haystackLen, needle, needleLen);
+}
+
 int eicCryptoMemCmp(const void* s1, const void* s2, size_t n) {
     return CRYPTO_memcmp(s1, s2, n);
 }
@@ -117,6 +126,25 @@
     return true;
 }
 
+bool eicNextId(uint32_t* id) {
+    uint32_t oldId = *id;
+    uint32_t newId = 0;
+
+    do {
+        union {
+            uint8_t value8;
+            uint32_t value32;
+        } value;
+        if (!eicOpsRandom(&value.value8, sizeof(value))) {
+            return false;
+        }
+        newId = value.value32;
+    } while (newId == oldId && newId == 0);
+
+    *id = newId;
+    return true;
+}
+
 bool eicOpsEncryptAes128Gcm(
         const uint8_t* key,    // Must be 16 bytes
         const uint8_t* nonce,  // Must be 12 bytes
@@ -239,25 +267,42 @@
 
 bool eicOpsCreateCredentialKey(uint8_t privateKey[EIC_P256_PRIV_KEY_SIZE], const uint8_t* challenge,
                                size_t challengeSize, const uint8_t* applicationId,
-                               size_t applicationIdSize, bool testCredential, uint8_t* cert,
-                               size_t* certSize) {
-    vector<uint8_t> challengeVec(challengeSize);
-    memcpy(challengeVec.data(), challenge, challengeSize);
-
-    vector<uint8_t> applicationIdVec(applicationIdSize);
-    memcpy(applicationIdVec.data(), applicationId, applicationIdSize);
-
-    optional<std::pair<vector<uint8_t>, vector<vector<uint8_t>>>> ret =
-            android::hardware::identity::support::createEcKeyPairAndAttestation(
-                    challengeVec, applicationIdVec, testCredential);
-    if (!ret) {
-        eicDebug("Error generating CredentialKey and attestation");
-        return false;
+                               size_t applicationIdSize, bool testCredential,
+                               const uint8_t* attestationKeyBlob, size_t attestationKeyBlobSize,
+                               const uint8_t* attestationKeyCert, size_t attestationKeyCertSize,
+                               uint8_t* cert, size_t* certSize) {
+    vector<uint8_t> flatChain;
+    vector<uint8_t> keyPair;
+    vector<uint8_t> challengeVec(challenge, challenge + challengeSize);
+    vector<uint8_t> applicationIdVec(applicationId, applicationId + applicationIdSize);
+    if (attestationKeyBlob && attestationKeyBlobSize > 0 && attestationKeyCert &&
+        attestationKeyCertSize > 0) {
+        vector<uint8_t> attestationKeyBlobVec(attestationKeyBlob,
+                                              attestationKeyBlob + attestationKeyBlobSize);
+        vector<uint8_t> attestationKeyCertVec(attestationKeyCert,
+                                              attestationKeyCert + attestationKeyCertSize);
+        optional<std::pair<vector<uint8_t>, vector<uint8_t>>> keyAndCert =
+                android::hardware::identity::support::createEcKeyPairWithAttestationKey(
+                        challengeVec, applicationIdVec, attestationKeyBlobVec,
+                        attestationKeyCertVec, testCredential);
+        if (!keyAndCert) {
+            eicDebug("Error generating CredentialKey and attestation");
+            return false;
+        }
+        keyPair = std::move(keyAndCert->first);
+        flatChain = std::move(keyAndCert->second);
+    } else {
+        optional<std::pair<vector<uint8_t>, vector<vector<uint8_t>>>> ret =
+                android::hardware::identity::support::createEcKeyPairAndAttestation(
+                        challengeVec, applicationIdVec, testCredential);
+        if (!ret) {
+            eicDebug("Error generating CredentialKey and attestation");
+            return false;
+        }
+        keyPair = std::move(ret->first);
+        flatChain = android::hardware::identity::support::certificateChainJoin(ret->second);
     }
 
-    // Extract certificate chain.
-    vector<uint8_t> flatChain =
-            android::hardware::identity::support::certificateChainJoin(ret.value().second);
     if (*certSize < flatChain.size()) {
         eicDebug("Buffer for certificate is only %zd bytes long, need %zd bytes", *certSize,
                  flatChain.size());
@@ -268,7 +313,7 @@
 
     // Extract private key.
     optional<vector<uint8_t>> privKey =
-            android::hardware::identity::support::ecKeyPairGetPrivateKey(ret.value().first);
+            android::hardware::identity::support::ecKeyPairGetPrivateKey(keyPair);
     if (!privKey) {
         eicDebug("Error extracting private key");
         return false;
@@ -492,10 +537,12 @@
 #ifdef EIC_DEBUG
 
 void eicPrint(const char* format, ...) {
+    char buf[1024];
     va_list args;
     va_start(args, format);
-    vfprintf(stderr, format, args);
+    vsnprintf(buf, sizeof(buf), format, args);
     va_end(args);
+    LOG(INFO) << buf;
 }
 
 void eicHexdump(const char* message, const uint8_t* data, size_t dataSize) {
diff --git a/identity/aidl/default/EicTests.cpp b/identity/aidl/default/EicTests.cpp
index a28080d..7b69b75 100644
--- a/identity/aidl/default/EicTests.cpp
+++ b/identity/aidl/default/EicTests.cpp
@@ -66,7 +66,8 @@
     // Then present data from it...
     //
     FakeSecureHardwarePresentationProxy presentationProxy;
-    ASSERT_TRUE(presentationProxy.initialize(isTestCredential, docType, credData.value()));
+    ASSERT_TRUE(presentationProxy.initialize(0 /* sessionId */, isTestCredential, docType,
+                                             credData.value()));
     AccessCheckResult res =
             presentationProxy.startRetrieveEntryValue(nameSpace, name, 1, content.size(), acpIds);
     ASSERT_EQ(res, AccessCheckResult::kNoAccessControlProfiles);
diff --git a/identity/aidl/default/FakeSecureHardwareProxy.cpp b/identity/aidl/default/FakeSecureHardwareProxy.cpp
index 287ffb8..9b9a749 100644
--- a/identity/aidl/default/FakeSecureHardwareProxy.cpp
+++ b/identity/aidl/default/FakeSecureHardwareProxy.cpp
@@ -23,6 +23,7 @@
 #include <android-base/logging.h>
 #include <android-base/stringprintf.h>
 #include <string.h>
+#include <map>
 
 #include <openssl/sha.h>
 
@@ -52,48 +53,148 @@
 
 // ----------------------------------------------------------------------
 
-FakeSecureHardwareProvisioningProxy::FakeSecureHardwareProvisioningProxy() {}
+// The singleton EicProvisioning object used everywhere.
+//
+EicProvisioning FakeSecureHardwareProvisioningProxy::ctx_;
 
-FakeSecureHardwareProvisioningProxy::~FakeSecureHardwareProvisioningProxy() {}
-
-bool FakeSecureHardwareProvisioningProxy::shutdown() {
-    LOG(INFO) << "FakeSecureHardwarePresentationProxy shutdown";
-    return true;
+FakeSecureHardwareProvisioningProxy::~FakeSecureHardwareProvisioningProxy() {
+    if (id_ != 0) {
+        shutdown();
+    }
 }
 
 bool FakeSecureHardwareProvisioningProxy::initialize(bool testCredential) {
-    LOG(INFO) << "FakeSecureHardwareProvisioningProxy created, sizeof(EicProvisioning): "
-              << sizeof(EicProvisioning);
-    return eicProvisioningInit(&ctx_, testCredential);
+    if (id_ != 0) {
+        LOG(WARNING) << "Proxy is already initialized";
+        return false;
+    }
+    bool initialized = eicProvisioningInit(&ctx_, testCredential);
+    if (!initialized) {
+        return false;
+    }
+    optional<uint32_t> id = getId();
+    if (!id) {
+        LOG(WARNING) << "Error getting id";
+        return false;
+    }
+    id_ = id.value();
+    return true;
 }
 
 bool FakeSecureHardwareProvisioningProxy::initializeForUpdate(
-        bool testCredential, string docType, vector<uint8_t> encryptedCredentialKeys) {
-    return eicProvisioningInitForUpdate(&ctx_, testCredential, docType.c_str(),
-                                        encryptedCredentialKeys.data(),
-                                        encryptedCredentialKeys.size());
+        bool testCredential, const string& docType,
+        const vector<uint8_t>& encryptedCredentialKeys) {
+    if (id_ != 0) {
+        LOG(WARNING) << "Proxy is already initialized";
+        return false;
+    }
+    bool initialized = eicProvisioningInitForUpdate(&ctx_, testCredential, docType.c_str(),
+                                                    docType.size(), encryptedCredentialKeys.data(),
+                                                    encryptedCredentialKeys.size());
+    if (!initialized) {
+        return false;
+    }
+    optional<uint32_t> id = getId();
+    if (!id) {
+        LOG(WARNING) << "Error getting id";
+        return false;
+    }
+    id_ = id.value();
+    return true;
+}
+
+optional<uint32_t> FakeSecureHardwareProvisioningProxy::getId() {
+    uint32_t id;
+    if (!eicProvisioningGetId(&ctx_, &id)) {
+        return std::nullopt;
+    }
+    return id;
+}
+
+bool FakeSecureHardwareProvisioningProxy::validateId(const string& callerName) {
+    if (id_ == 0) {
+        LOG(WARNING) << "FakeSecureHardwareProvisioningProxy::" << callerName
+                     << ": While validating expected id is 0";
+        return false;
+    }
+    optional<uint32_t> id = getId();
+    if (!id) {
+        LOG(WARNING) << "FakeSecureHardwareProvisioningProxy::" << callerName
+                     << ": Error getting id for validating";
+        return false;
+    }
+    if (id.value() != id_) {
+        LOG(WARNING) << "FakeSecureHardwareProvisioningProxy::" << callerName
+                     << ": While validating expected id " << id_ << " but got " << id.value();
+        return false;
+    }
+    return true;
+}
+
+bool FakeSecureHardwareProvisioningProxy::shutdown() {
+    bool validated = validateId(__func__);
+    id_ = 0;
+    if (!validated) {
+        return false;
+    }
+    if (!eicProvisioningShutdown(&ctx_)) {
+        LOG(INFO) << "Error shutting down provisioning";
+        return false;
+    }
+    return true;
 }
 
 // Returns public key certificate.
 optional<vector<uint8_t>> FakeSecureHardwareProvisioningProxy::createCredentialKey(
         const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId) {
+    if (!validateId(__func__)) {
+        return std::nullopt;
+    }
+
     uint8_t publicKeyCert[4096];
     size_t publicKeyCertSize = sizeof publicKeyCert;
     if (!eicProvisioningCreateCredentialKey(&ctx_, challenge.data(), challenge.size(),
                                             applicationId.data(), applicationId.size(),
-                                            publicKeyCert, &publicKeyCertSize)) {
-        return {};
+                                            /*attestationKeyBlob=*/nullptr,
+                                            /*attestationKeyBlobSize=*/0,
+                                            /*attestationKeyCert=*/nullptr,
+                                            /*attestationKeyCertSize=*/0, publicKeyCert,
+                                            &publicKeyCertSize)) {
+        return std::nullopt;
     }
     vector<uint8_t> pubKeyCert(publicKeyCertSize);
     memcpy(pubKeyCert.data(), publicKeyCert, publicKeyCertSize);
     return pubKeyCert;
 }
 
+optional<vector<uint8_t>> FakeSecureHardwareProvisioningProxy::createCredentialKeyUsingRkp(
+        const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId,
+        const vector<uint8_t>& attestationKeyBlob, const vector<uint8_t>& attstationKeyCert) {
+    size_t publicKeyCertSize = 4096;
+    vector<uint8_t> publicKeyCert(publicKeyCertSize);
+    if (!eicProvisioningCreateCredentialKey(&ctx_, challenge.data(), challenge.size(),
+                                            applicationId.data(), applicationId.size(),
+                                            attestationKeyBlob.data(), attestationKeyBlob.size(),
+                                            attstationKeyCert.data(), attstationKeyCert.size(),
+                                            publicKeyCert.data(), &publicKeyCertSize)) {
+        LOG(ERROR) << "error creating credential key";
+        return std::nullopt;
+    }
+    publicKeyCert.resize(publicKeyCertSize);
+    return publicKeyCert;
+}
+
 bool FakeSecureHardwareProvisioningProxy::startPersonalization(
-        int accessControlProfileCount, vector<int> entryCounts, const string& docType,
+        int accessControlProfileCount, const vector<int>& entryCounts, const string& docType,
         size_t expectedProofOfProvisioningSize) {
-    if (!eicProvisioningStartPersonalization(&ctx_, accessControlProfileCount, entryCounts.data(),
-                                             entryCounts.size(), docType.c_str(),
+    if (!validateId(__func__)) {
+        return false;
+    }
+
+    if (!eicProvisioningStartPersonalization(&ctx_, accessControlProfileCount,
+                                             entryCounts.data(),
+                                             entryCounts.size(),
+                                             docType.c_str(), docType.size(),
                                              expectedProofOfProvisioningSize)) {
         return false;
     }
@@ -104,11 +205,17 @@
 optional<vector<uint8_t>> FakeSecureHardwareProvisioningProxy::addAccessControlProfile(
         int id, const vector<uint8_t>& readerCertificate, bool userAuthenticationRequired,
         uint64_t timeoutMillis, uint64_t secureUserId) {
+    if (!validateId(__func__)) {
+        return std::nullopt;
+    }
+
     vector<uint8_t> mac(28);
+    uint8_t scratchSpace[512];
     if (!eicProvisioningAddAccessControlProfile(
                 &ctx_, id, readerCertificate.data(), readerCertificate.size(),
-                userAuthenticationRequired, timeoutMillis, secureUserId, mac.data())) {
-        return {};
+                userAuthenticationRequired, timeoutMillis, secureUserId, mac.data(),
+                scratchSpace, sizeof(scratchSpace))) {
+        return std::nullopt;
     }
     return mac;
 }
@@ -116,33 +223,56 @@
 bool FakeSecureHardwareProvisioningProxy::beginAddEntry(const vector<int>& accessControlProfileIds,
                                                         const string& nameSpace, const string& name,
                                                         uint64_t entrySize) {
+    if (!validateId(__func__)) {
+        return false;
+    }
+
     uint8_t scratchSpace[512];
-    return eicProvisioningBeginAddEntry(&ctx_, accessControlProfileIds.data(),
-                                        accessControlProfileIds.size(), nameSpace.c_str(),
-                                        name.c_str(), entrySize, scratchSpace, sizeof scratchSpace);
+    vector<uint8_t> uint8AccessControlProfileIds;
+    for (size_t i = 0; i < accessControlProfileIds.size(); i++) {
+        uint8AccessControlProfileIds.push_back(accessControlProfileIds[i] & 0xFF);
+    }
+
+    return eicProvisioningBeginAddEntry(&ctx_, uint8AccessControlProfileIds.data(),
+                                        uint8AccessControlProfileIds.size(), nameSpace.c_str(),
+                                        nameSpace.size(), name.c_str(), name.size(), entrySize,
+                                        scratchSpace, sizeof(scratchSpace));
 }
 
 // Returns encryptedContent.
 optional<vector<uint8_t>> FakeSecureHardwareProvisioningProxy::addEntryValue(
         const vector<int>& accessControlProfileIds, const string& nameSpace, const string& name,
         const vector<uint8_t>& content) {
+    if (!validateId(__func__)) {
+        return std::nullopt;
+    }
+
     vector<uint8_t> eicEncryptedContent;
     uint8_t scratchSpace[512];
+    vector<uint8_t> uint8AccessControlProfileIds;
+    for (size_t i = 0; i < accessControlProfileIds.size(); i++) {
+        uint8AccessControlProfileIds.push_back(accessControlProfileIds[i] & 0xFF);
+    }
+
     eicEncryptedContent.resize(content.size() + 28);
     if (!eicProvisioningAddEntryValue(
-                &ctx_, accessControlProfileIds.data(), accessControlProfileIds.size(),
-                nameSpace.c_str(), name.c_str(), content.data(), content.size(),
-                eicEncryptedContent.data(), scratchSpace, sizeof scratchSpace)) {
-        return {};
+                &ctx_, uint8AccessControlProfileIds.data(), uint8AccessControlProfileIds.size(),
+                nameSpace.c_str(), nameSpace.size(), name.c_str(), name.size(), content.data(),
+                content.size(), eicEncryptedContent.data(), scratchSpace, sizeof(scratchSpace))) {
+        return std::nullopt;
     }
     return eicEncryptedContent;
 }
 
 // Returns signatureOfToBeSigned (EIC_ECDSA_P256_SIGNATURE_SIZE bytes).
 optional<vector<uint8_t>> FakeSecureHardwareProvisioningProxy::finishAddingEntries() {
+    if (!validateId(__func__)) {
+        return std::nullopt;
+    }
+
     vector<uint8_t> signatureOfToBeSigned(EIC_ECDSA_P256_SIGNATURE_SIZE);
     if (!eicProvisioningFinishAddingEntries(&ctx_, signatureOfToBeSigned.data())) {
-        return {};
+        return std::nullopt;
     }
     return signatureOfToBeSigned;
 }
@@ -150,11 +280,15 @@
 // Returns encryptedCredentialKeys.
 optional<vector<uint8_t>> FakeSecureHardwareProvisioningProxy::finishGetCredentialData(
         const string& docType) {
+    if (!validateId(__func__)) {
+        return std::nullopt;
+    }
+
     vector<uint8_t> encryptedCredentialKeys(116);
     size_t size = encryptedCredentialKeys.size();
-    if (!eicProvisioningFinishGetCredentialData(&ctx_, docType.c_str(),
+    if (!eicProvisioningFinishGetCredentialData(&ctx_, docType.c_str(), docType.size(),
                                                 encryptedCredentialKeys.data(), &size)) {
-        return {};
+        return std::nullopt;
     }
     encryptedCredentialKeys.resize(size);
     return encryptedCredentialKeys;
@@ -162,28 +296,208 @@
 
 // ----------------------------------------------------------------------
 
-FakeSecureHardwarePresentationProxy::FakeSecureHardwarePresentationProxy() {}
+// The singleton EicSession object used everywhere.
+//
+EicSession FakeSecureHardwareSessionProxy::ctx_;
 
-FakeSecureHardwarePresentationProxy::~FakeSecureHardwarePresentationProxy() {}
+FakeSecureHardwareSessionProxy::~FakeSecureHardwareSessionProxy() {
+    if (id_ != 0) {
+        shutdown();
+    }
+}
 
-bool FakeSecureHardwarePresentationProxy::initialize(bool testCredential, string docType,
-                                                     vector<uint8_t> encryptedCredentialKeys) {
-    LOG(INFO) << "FakeSecureHardwarePresentationProxy created, sizeof(EicPresentation): "
-              << sizeof(EicPresentation);
-    return eicPresentationInit(&ctx_, testCredential, docType.c_str(),
-                               encryptedCredentialKeys.data(), encryptedCredentialKeys.size());
+bool FakeSecureHardwareSessionProxy::initialize() {
+    if (id_ != 0) {
+        LOG(WARNING) << "Proxy is already initialized";
+        return false;
+    }
+    bool initialized = eicSessionInit(&ctx_);
+    if (!initialized) {
+        return false;
+    }
+    optional<uint32_t> id = getId();
+    if (!id) {
+        LOG(WARNING) << "Error getting id";
+        return false;
+    }
+    id_ = id.value();
+    return true;
+}
+
+optional<uint32_t> FakeSecureHardwareSessionProxy::getId() {
+    uint32_t id;
+    if (!eicSessionGetId(&ctx_, &id)) {
+        return std::nullopt;
+    }
+    return id;
+}
+
+bool FakeSecureHardwareSessionProxy::shutdown() {
+    bool validated = validateId(__func__);
+    id_ = 0;
+    if (!validated) {
+        return false;
+    }
+    if (!eicSessionShutdown(&ctx_)) {
+        LOG(INFO) << "Error shutting down session";
+        return false;
+    }
+    return true;
+}
+
+bool FakeSecureHardwareSessionProxy::validateId(const string& callerName) {
+    if (id_ == 0) {
+        LOG(WARNING) << "FakeSecureHardwareSessionProxy::" << callerName
+                     << ": While validating expected id is 0";
+        return false;
+    }
+    optional<uint32_t> id = getId();
+    if (!id) {
+        LOG(WARNING) << "FakeSecureHardwareSessionProxy::" << callerName
+                     << ": Error getting id for validating";
+        return false;
+    }
+    if (id.value() != id_) {
+        LOG(WARNING) << "FakeSecureHardwareSessionProxy::" << callerName
+                     << ": While validating expected id " << id_ << " but got " << id.value();
+        return false;
+    }
+    return true;
+}
+
+optional<uint64_t> FakeSecureHardwareSessionProxy::getAuthChallenge() {
+    if (!validateId(__func__)) {
+        return std::nullopt;
+    }
+
+    uint64_t authChallenge;
+    if (!eicSessionGetAuthChallenge(&ctx_, &authChallenge)) {
+        return std::nullopt;
+    }
+    return authChallenge;
+}
+
+optional<vector<uint8_t>> FakeSecureHardwareSessionProxy::getEphemeralKeyPair() {
+    if (!validateId(__func__)) {
+        return std::nullopt;
+    }
+
+    vector<uint8_t> priv(EIC_P256_PRIV_KEY_SIZE);
+    if (!eicSessionGetEphemeralKeyPair(&ctx_, priv.data())) {
+        return std::nullopt;
+    }
+    return priv;
+}
+
+bool FakeSecureHardwareSessionProxy::setReaderEphemeralPublicKey(
+        const vector<uint8_t>& readerEphemeralPublicKey) {
+    if (!validateId(__func__)) {
+        return false;
+    }
+
+    return eicSessionSetReaderEphemeralPublicKey(&ctx_, readerEphemeralPublicKey.data());
+}
+
+bool FakeSecureHardwareSessionProxy::setSessionTranscript(
+        const vector<uint8_t>& sessionTranscript) {
+    if (!validateId(__func__)) {
+        return false;
+    }
+
+    return eicSessionSetSessionTranscript(&ctx_, sessionTranscript.data(),
+                                          sessionTranscript.size());
+}
+
+// ----------------------------------------------------------------------
+
+// The singleton EicPresentation object used everywhere.
+//
+EicPresentation FakeSecureHardwarePresentationProxy::ctx_;
+
+FakeSecureHardwarePresentationProxy::~FakeSecureHardwarePresentationProxy() {
+    if (id_ != 0) {
+        shutdown();
+    }
+}
+
+bool FakeSecureHardwarePresentationProxy::initialize(
+        uint32_t sessionId, bool testCredential, const string& docType,
+        const vector<uint8_t>& encryptedCredentialKeys) {
+    if (id_ != 0) {
+        LOG(WARNING) << "Proxy is already initialized";
+        return false;
+    }
+    bool initialized =
+            eicPresentationInit(&ctx_, sessionId, testCredential, docType.c_str(), docType.size(),
+                                encryptedCredentialKeys.data(), encryptedCredentialKeys.size());
+    if (!initialized) {
+        return false;
+    }
+    optional<uint32_t> id = getId();
+    if (!id) {
+        LOG(WARNING) << "Error getting id";
+        return false;
+    }
+    id_ = id.value();
+    return true;
+}
+
+optional<uint32_t> FakeSecureHardwarePresentationProxy::getId() {
+    uint32_t id;
+    if (!eicPresentationGetId(&ctx_, &id)) {
+        return std::nullopt;
+    }
+    return id;
+}
+
+bool FakeSecureHardwarePresentationProxy::validateId(const string& callerName) {
+    if (id_ == 0) {
+        LOG(WARNING) << "FakeSecureHardwarePresentationProxy::" << callerName
+                     << ": While validating expected id is 0";
+        return false;
+    }
+    optional<uint32_t> id = getId();
+    if (!id) {
+        LOG(WARNING) << "FakeSecureHardwarePresentationProxy::" << callerName
+                     << ": Error getting id for validating";
+        return false;
+    }
+    if (id.value() != id_) {
+        LOG(WARNING) << "FakeSecureHardwarePresentationProxy::" << callerName
+                     << ": While validating expected id " << id_ << " but got " << id.value();
+        return false;
+    }
+    return true;
+}
+
+bool FakeSecureHardwarePresentationProxy::shutdown() {
+    bool validated = validateId(__func__);
+    id_ = 0;
+    if (!validated) {
+        return false;
+    }
+    if (!eicPresentationShutdown(&ctx_)) {
+        LOG(INFO) << "Error shutting down presentation";
+        return false;
+    }
+    return true;
 }
 
 // Returns publicKeyCert (1st component) and signingKeyBlob (2nd component)
 optional<pair<vector<uint8_t>, vector<uint8_t>>>
-FakeSecureHardwarePresentationProxy::generateSigningKeyPair(string docType, time_t now) {
+FakeSecureHardwarePresentationProxy::generateSigningKeyPair(const string& docType, time_t now) {
+    if (!validateId(__func__)) {
+        return std::nullopt;
+    }
+
     uint8_t publicKeyCert[512];
     size_t publicKeyCertSize = sizeof(publicKeyCert);
     vector<uint8_t> signingKeyBlob(60);
 
-    if (!eicPresentationGenerateSigningKeyPair(&ctx_, docType.c_str(), now, publicKeyCert,
-                                               &publicKeyCertSize, signingKeyBlob.data())) {
-        return {};
+    if (!eicPresentationGenerateSigningKeyPair(&ctx_, docType.c_str(), docType.size(), now,
+                                               publicKeyCert, &publicKeyCertSize,
+                                               signingKeyBlob.data())) {
+        return std::nullopt;
     }
 
     vector<uint8_t> cert;
@@ -195,33 +509,44 @@
 
 // Returns private key
 optional<vector<uint8_t>> FakeSecureHardwarePresentationProxy::createEphemeralKeyPair() {
+    if (!validateId(__func__)) {
+        return std::nullopt;
+    }
+
     vector<uint8_t> priv(EIC_P256_PRIV_KEY_SIZE);
     if (!eicPresentationCreateEphemeralKeyPair(&ctx_, priv.data())) {
-        return {};
+        return std::nullopt;
     }
     return priv;
 }
 
 optional<uint64_t> FakeSecureHardwarePresentationProxy::createAuthChallenge() {
+    if (!validateId(__func__)) {
+        return std::nullopt;
+    }
+
     uint64_t challenge;
     if (!eicPresentationCreateAuthChallenge(&ctx_, &challenge)) {
-        return {};
+        return std::nullopt;
     }
     return challenge;
 }
 
-bool FakeSecureHardwarePresentationProxy::shutdown() {
-    LOG(INFO) << "FakeSecureHardwarePresentationProxy shutdown";
-    return true;
-}
-
 bool FakeSecureHardwarePresentationProxy::pushReaderCert(const vector<uint8_t>& certX509) {
+    if (!validateId(__func__)) {
+        return false;
+    }
+
     return eicPresentationPushReaderCert(&ctx_, certX509.data(), certX509.size());
 }
 
 bool FakeSecureHardwarePresentationProxy::validateRequestMessage(
         const vector<uint8_t>& sessionTranscript, const vector<uint8_t>& requestMessage,
         int coseSignAlg, const vector<uint8_t>& readerSignatureOfToBeSigned) {
+    if (!validateId(__func__)) {
+        return false;
+    }
+
     return eicPresentationValidateRequestMessage(
             &ctx_, sessionTranscript.data(), sessionTranscript.size(), requestMessage.data(),
             requestMessage.size(), coseSignAlg, readerSignatureOfToBeSigned.data(),
@@ -233,6 +558,10 @@
         int hardwareAuthenticatorType, uint64_t timeStamp, const vector<uint8_t>& mac,
         uint64_t verificationTokenChallenge, uint64_t verificationTokenTimestamp,
         int verificationTokenSecurityLevel, const vector<uint8_t>& verificationTokenMac) {
+    if (!validateId(__func__)) {
+        return false;
+    }
+
     return eicPresentationSetAuthToken(&ctx_, challenge, secureUserId, authenticatorId,
                                        hardwareAuthenticatorType, timeStamp, mac.data(), mac.size(),
                                        verificationTokenChallenge, verificationTokenTimestamp,
@@ -243,17 +572,27 @@
 optional<bool> FakeSecureHardwarePresentationProxy::validateAccessControlProfile(
         int id, const vector<uint8_t>& readerCertificate, bool userAuthenticationRequired,
         int timeoutMillis, uint64_t secureUserId, const vector<uint8_t>& mac) {
+    if (!validateId(__func__)) {
+        return std::nullopt;
+    }
+
     bool accessGranted = false;
+    uint8_t scratchSpace[512];
     if (!eicPresentationValidateAccessControlProfile(&ctx_, id, readerCertificate.data(),
                                                      readerCertificate.size(),
                                                      userAuthenticationRequired, timeoutMillis,
-                                                     secureUserId, mac.data(), &accessGranted)) {
-        return {};
+                                                     secureUserId, mac.data(), &accessGranted,
+                                                     scratchSpace, sizeof(scratchSpace))) {
+        return std::nullopt;
     }
     return accessGranted;
 }
 
 bool FakeSecureHardwarePresentationProxy::startRetrieveEntries() {
+    if (!validateId(__func__)) {
+        return false;
+    }
+
     return eicPresentationStartRetrieveEntries(&ctx_);
 }
 
@@ -261,24 +600,38 @@
         const vector<uint8_t>& sessionTranscript, const vector<uint8_t>& readerEphemeralPublicKey,
         const vector<uint8_t>& signingKeyBlob, const string& docType,
         unsigned int numNamespacesWithValues, size_t expectedProofOfProvisioningSize) {
+    if (!validateId(__func__)) {
+        return false;
+    }
+
     if (signingKeyBlob.size() != 60) {
         eicDebug("Unexpected size %zd of signingKeyBlob, expected 60", signingKeyBlob.size());
         return false;
     }
     return eicPresentationCalcMacKey(&ctx_, sessionTranscript.data(), sessionTranscript.size(),
                                      readerEphemeralPublicKey.data(), signingKeyBlob.data(),
-                                     docType.c_str(), numNamespacesWithValues,
+                                     docType.c_str(), docType.size(), numNamespacesWithValues,
                                      expectedProofOfProvisioningSize);
 }
 
 AccessCheckResult FakeSecureHardwarePresentationProxy::startRetrieveEntryValue(
         const string& nameSpace, const string& name, unsigned int newNamespaceNumEntries,
         int32_t entrySize, const vector<int32_t>& accessControlProfileIds) {
+    if (!validateId(__func__)) {
+        return AccessCheckResult::kFailed;
+    }
+
     uint8_t scratchSpace[512];
+    vector<uint8_t> uint8AccessControlProfileIds;
+    for (size_t i = 0; i < accessControlProfileIds.size(); i++) {
+        uint8AccessControlProfileIds.push_back(accessControlProfileIds[i] & 0xFF);
+    }
+
     EicAccessCheckResult result = eicPresentationStartRetrieveEntryValue(
-            &ctx_, nameSpace.c_str(), name.c_str(), newNamespaceNumEntries, entrySize,
-            accessControlProfileIds.data(), accessControlProfileIds.size(), scratchSpace,
-            sizeof scratchSpace);
+            &ctx_, nameSpace.c_str(), nameSpace.size(), name.c_str(), name.size(),
+            newNamespaceNumEntries, entrySize, uint8AccessControlProfileIds.data(),
+            uint8AccessControlProfileIds.size(), scratchSpace,
+            sizeof(scratchSpace));
     switch (result) {
         case EIC_ACCESS_CHECK_RESULT_OK:
             return AccessCheckResult::kOk;
@@ -298,23 +651,37 @@
 optional<vector<uint8_t>> FakeSecureHardwarePresentationProxy::retrieveEntryValue(
         const vector<uint8_t>& encryptedContent, const string& nameSpace, const string& name,
         const vector<int32_t>& accessControlProfileIds) {
+    if (!validateId(__func__)) {
+        return std::nullopt;
+    }
+
     uint8_t scratchSpace[512];
+    vector<uint8_t> uint8AccessControlProfileIds;
+    for (size_t i = 0; i < accessControlProfileIds.size(); i++) {
+        uint8AccessControlProfileIds.push_back(accessControlProfileIds[i] & 0xFF);
+    }
+
     vector<uint8_t> content;
     content.resize(encryptedContent.size() - 28);
     if (!eicPresentationRetrieveEntryValue(
                 &ctx_, encryptedContent.data(), encryptedContent.size(), content.data(),
-                nameSpace.c_str(), name.c_str(), accessControlProfileIds.data(),
-                accessControlProfileIds.size(), scratchSpace, sizeof scratchSpace)) {
-        return {};
+                nameSpace.c_str(), nameSpace.size(), name.c_str(), name.size(),
+                uint8AccessControlProfileIds.data(), uint8AccessControlProfileIds.size(),
+                scratchSpace, sizeof(scratchSpace))) {
+        return std::nullopt;
     }
     return content;
 }
 
 optional<vector<uint8_t>> FakeSecureHardwarePresentationProxy::finishRetrieval() {
+    if (!validateId(__func__)) {
+        return std::nullopt;
+    }
+
     vector<uint8_t> mac(32);
     size_t macSize = 32;
     if (!eicPresentationFinishRetrieval(&ctx_, mac.data(), &macSize)) {
-        return {};
+        return std::nullopt;
     }
     mac.resize(macSize);
     return mac;
@@ -323,11 +690,15 @@
 optional<vector<uint8_t>> FakeSecureHardwarePresentationProxy::deleteCredential(
         const string& docType, const vector<uint8_t>& challenge, bool includeChallenge,
         size_t proofOfDeletionCborSize) {
+    if (!validateId(__func__)) {
+        return std::nullopt;
+    }
+
     vector<uint8_t> signatureOfToBeSigned(EIC_ECDSA_P256_SIGNATURE_SIZE);
-    if (!eicPresentationDeleteCredential(&ctx_, docType.c_str(), challenge.data(), challenge.size(),
-                                         includeChallenge, proofOfDeletionCborSize,
-                                         signatureOfToBeSigned.data())) {
-        return {};
+    if (!eicPresentationDeleteCredential(&ctx_, docType.c_str(), docType.size(), challenge.data(),
+                                         challenge.size(), includeChallenge,
+                                         proofOfDeletionCborSize, signatureOfToBeSigned.data())) {
+        return std::nullopt;
     }
     return signatureOfToBeSigned;
 }
@@ -335,11 +706,15 @@
 optional<vector<uint8_t>> FakeSecureHardwarePresentationProxy::proveOwnership(
         const string& docType, bool testCredential, const vector<uint8_t>& challenge,
         size_t proofOfOwnershipCborSize) {
+    if (!validateId(__func__)) {
+        return std::nullopt;
+    }
+
     vector<uint8_t> signatureOfToBeSigned(EIC_ECDSA_P256_SIGNATURE_SIZE);
-    if (!eicPresentationProveOwnership(&ctx_, docType.c_str(), testCredential, challenge.data(),
-                                       challenge.size(), proofOfOwnershipCborSize,
+    if (!eicPresentationProveOwnership(&ctx_, docType.c_str(), docType.size(), testCredential,
+                                       challenge.data(), challenge.size(), proofOfOwnershipCborSize,
                                        signatureOfToBeSigned.data())) {
-        return {};
+        return std::nullopt;
     }
     return signatureOfToBeSigned;
 }
diff --git a/identity/aidl/default/FakeSecureHardwareProxy.h b/identity/aidl/default/FakeSecureHardwareProxy.h
index 6852c1a..2512074 100644
--- a/identity/aidl/default/FakeSecureHardwareProxy.h
+++ b/identity/aidl/default/FakeSecureHardwareProxy.h
@@ -27,21 +27,28 @@
 //
 class FakeSecureHardwareProvisioningProxy : public SecureHardwareProvisioningProxy {
   public:
-    FakeSecureHardwareProvisioningProxy();
+    FakeSecureHardwareProvisioningProxy() = default;
     virtual ~FakeSecureHardwareProvisioningProxy();
 
     bool initialize(bool testCredential) override;
 
-    bool initializeForUpdate(bool testCredential, string docType,
-                             vector<uint8_t> encryptedCredentialKeys) override;
+    bool initializeForUpdate(bool testCredential, const string& docType,
+                             const vector<uint8_t>& encryptedCredentialKeys) override;
 
     bool shutdown() override;
 
+    optional<uint32_t> getId() override;
+
     // Returns public key certificate.
     optional<vector<uint8_t>> createCredentialKey(const vector<uint8_t>& challenge,
                                                   const vector<uint8_t>& applicationId) override;
 
-    bool startPersonalization(int accessControlProfileCount, vector<int> entryCounts,
+    optional<vector<uint8_t>> createCredentialKeyUsingRkp(
+            const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId,
+            const vector<uint8_t>& attestationKeyBlob,
+            const vector<uint8_t>& attestationKeyCert) override;
+
+    bool startPersonalization(int accessControlProfileCount, const vector<int>& entryCounts,
                               const string& docType,
                               size_t expectedProofOfProvisioningSize) override;
 
@@ -67,21 +74,81 @@
     optional<vector<uint8_t>> finishGetCredentialData(const string& docType) override;
 
   protected:
-    EicProvisioning ctx_;
+    // See docs for id_.
+    //
+    bool validateId(const string& callerName);
+
+    // We use a singleton libeic object, shared by all proxy instances.  This is to
+    // properly simulate a situation where libeic is used on constrained hardware
+    // with only enough RAM for a single instance of the libeic object.
+    //
+    static EicProvisioning ctx_;
+
+    // On the HAL side we keep track of the ID that was assigned to the libeic object
+    // created in secure hardware. For every call into libeic we validate that this
+    // identifier matches what is on the secure side. This is what the validateId()
+    // method does.
+    //
+    uint32_t id_ = 0;
+};
+
+// This implementation uses libEmbeddedIC in-process.
+//
+class FakeSecureHardwareSessionProxy : public SecureHardwareSessionProxy {
+  public:
+    FakeSecureHardwareSessionProxy() = default;
+    virtual ~FakeSecureHardwareSessionProxy();
+
+    bool initialize() override;
+
+    bool shutdown() override;
+
+    optional<uint32_t> getId() override;
+
+    optional<uint64_t> getAuthChallenge() override;
+
+    // Returns private key
+    optional<vector<uint8_t>> getEphemeralKeyPair() override;
+
+    bool setReaderEphemeralPublicKey(const vector<uint8_t>& readerEphemeralPublicKey) override;
+
+    bool setSessionTranscript(const vector<uint8_t>& sessionTranscript) override;
+
+  protected:
+    // See docs for id_.
+    //
+    bool validateId(const string& callerName);
+
+    // We use a singleton libeic object, shared by all proxy instances.  This is to
+    // properly simulate a situation where libeic is used on constrained hardware
+    // with only enough RAM for a single instance of the libeic object.
+    //
+    static EicSession ctx_;
+
+    // On the HAL side we keep track of the ID that was assigned to the libeic object
+    // created in secure hardware. For every call into libeic we validate that this
+    // identifier matches what is on the secure side. This is what the validateId()
+    // method does.
+    //
+    uint32_t id_ = 0;
 };
 
 // This implementation uses libEmbeddedIC in-process.
 //
 class FakeSecureHardwarePresentationProxy : public SecureHardwarePresentationProxy {
   public:
-    FakeSecureHardwarePresentationProxy();
+    FakeSecureHardwarePresentationProxy() = default;
     virtual ~FakeSecureHardwarePresentationProxy();
 
-    bool initialize(bool testCredential, string docType,
-                    vector<uint8_t> encryptedCredentialKeys) override;
+    bool initialize(uint32_t sessionId, bool testCredential, const string& docType,
+                    const vector<uint8_t>& encryptedCredentialKeys) override;
+
+    bool shutdown() override;
+
+    optional<uint32_t> getId() override;
 
     // Returns publicKeyCert (1st component) and signingKeyBlob (2nd component)
-    optional<pair<vector<uint8_t>, vector<uint8_t>>> generateSigningKeyPair(string docType,
+    optional<pair<vector<uint8_t>, vector<uint8_t>>> generateSigningKeyPair(const string& docType,
                                                                             time_t now) override;
 
     // Returns private key
@@ -133,10 +200,23 @@
                                              const vector<uint8_t>& challenge,
                                              size_t proofOfOwnershipCborSize) override;
 
-    bool shutdown() override;
-
   protected:
-    EicPresentation ctx_;
+    // See docs for id_.
+    //
+    bool validateId(const string& callerName);
+
+    // We use a singleton libeic object, shared by all proxy instances.  This is to
+    // properly simulate a situation where libeic is used on constrained hardware
+    // with only enough RAM for a single instance of the libeic object.
+    //
+    static EicPresentation ctx_;
+
+    // On the HAL side we keep track of the ID that was assigned to the libeic object
+    // created in secure hardware. For every call into libeic we validate that this
+    // identifier matches what is on the secure side. This is what the validateId()
+    // method does.
+    //
+    uint32_t id_ = 0;
 };
 
 // Factory implementation.
@@ -150,6 +230,10 @@
         return new FakeSecureHardwareProvisioningProxy();
     }
 
+    sp<SecureHardwareSessionProxy> createSessionProxy() override {
+        return new FakeSecureHardwareSessionProxy();
+    }
+
     sp<SecureHardwarePresentationProxy> createPresentationProxy() override {
         return new FakeSecureHardwarePresentationProxy();
     }
diff --git a/identity/aidl/default/android.hardware.identity_credential.xml b/identity/aidl/default/android.hardware.identity_credential.xml
index 5149792..20b2710 100644
--- a/identity/aidl/default/android.hardware.identity_credential.xml
+++ b/identity/aidl/default/android.hardware.identity_credential.xml
@@ -14,5 +14,5 @@
      limitations under the License.
 -->
 <permissions>
-  <feature name="android.hardware.identity_credential" version="202101" />
+  <feature name="android.hardware.identity_credential" version="202201" />
 </permissions>
diff --git a/identity/aidl/default/common/IdentityCredential.cpp b/identity/aidl/default/common/IdentityCredential.cpp
index 95557b5..ff80752 100644
--- a/identity/aidl/default/common/IdentityCredential.cpp
+++ b/identity/aidl/default/common/IdentityCredential.cpp
@@ -72,14 +72,38 @@
     testCredential_ = testCredentialItem->value();
 
     encryptedCredentialKeys_ = encryptedCredentialKeysItem->value();
-    if (!hwProxy_->initialize(testCredential_, docType_, encryptedCredentialKeys_)) {
-        LOG(ERROR) << "hwProxy->initialize failed";
-        return false;
+
+    // If in a session, delay the initialization of the proxy.
+    //
+    if (!session_) {
+        ndk::ScopedAStatus status = ensureHwProxy();
+        if (!status.isOk()) {
+            LOG(ERROR) << "Error initializing hw proxy";
+            return IIdentityCredentialStore::STATUS_FAILED;
+        }
     }
 
     return IIdentityCredentialStore::STATUS_OK;
 }
 
+ndk::ScopedAStatus IdentityCredential::ensureHwProxy() {
+    if (hwProxy_) {
+        return ndk::ScopedAStatus::ok();
+    }
+    hwProxy_ = hwProxyFactory_->createPresentationProxy();
+    if (!hwProxy_) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED, "Error creating hw proxy"));
+    }
+    uint64_t sessionId = session_ ? session_->getSessionId() : EIC_PRESENTATION_ID_UNSET;
+    if (!hwProxy_->initialize(sessionId, testCredential_, docType_, encryptedCredentialKeys_)) {
+        hwProxy_.clear();
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED, "Error initializing hw proxy"));
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
 ndk::ScopedAStatus IdentityCredential::deleteCredential(
         vector<uint8_t>* outProofOfDeletionSignature) {
     return deleteCredentialCommon({}, false, outProofOfDeletionSignature);
@@ -93,6 +117,14 @@
 ndk::ScopedAStatus IdentityCredential::deleteCredentialCommon(
         const vector<uint8_t>& challenge, bool includeChallenge,
         vector<uint8_t>* outProofOfDeletionSignature) {
+    if (session_) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED, "Cannot be called in a session"));
+    }
+    ndk::ScopedAStatus status = ensureHwProxy();
+    if (!status.isOk()) {
+        return status;
+    }
     if (challenge.size() > 32) {
         return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
                 IIdentityCredentialStore::STATUS_INVALID_DATA, "Challenge too big"));
@@ -128,6 +160,14 @@
 
 ndk::ScopedAStatus IdentityCredential::proveOwnership(
         const vector<uint8_t>& challenge, vector<uint8_t>* outProofOfOwnershipSignature) {
+    if (session_) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED, "Cannot be called in a session"));
+    }
+    ndk::ScopedAStatus status = ensureHwProxy();
+    if (!status.isOk()) {
+        return status;
+    }
     if (challenge.size() > 32) {
         return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
                 IIdentityCredentialStore::STATUS_INVALID_DATA, "Challenge too big"));
@@ -159,6 +199,14 @@
 }
 
 ndk::ScopedAStatus IdentityCredential::createEphemeralKeyPair(vector<uint8_t>* outKeyPair) {
+    if (session_) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED, "Cannot be called in a session"));
+    }
+    ndk::ScopedAStatus status = ensureHwProxy();
+    if (!status.isOk()) {
+        return status;
+    }
     optional<vector<uint8_t>> ephemeralPriv = hwProxy_->createEphemeralKeyPair();
     if (!ephemeralPriv) {
         return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
@@ -186,11 +234,23 @@
 
 ndk::ScopedAStatus IdentityCredential::setReaderEphemeralPublicKey(
         const vector<uint8_t>& publicKey) {
+    if (session_) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED, "Cannot be called in a session"));
+    }
     readerPublicKey_ = publicKey;
     return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus IdentityCredential::createAuthChallenge(int64_t* outChallenge) {
+    if (session_) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED, "Cannot be called in a session"));
+    }
+    ndk::ScopedAStatus status = ensureHwProxy();
+    if (!status.isOk()) {
+        return status;
+    }
     optional<uint64_t> challenge = hwProxy_->createAuthChallenge();
     if (!challenge) {
         return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
@@ -217,16 +277,22 @@
         const HardwareAuthToken& authToken, const vector<uint8_t>& itemsRequest,
         const vector<uint8_t>& signingKeyBlob, const vector<uint8_t>& sessionTranscript,
         const vector<uint8_t>& readerSignature, const vector<int32_t>& requestCounts) {
-    std::unique_ptr<cppbor::Item> sessionTranscriptItem;
-    if (sessionTranscript.size() > 0) {
-        auto [item, _, message] = cppbor::parse(sessionTranscript);
-        if (item == nullptr) {
-            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
-                    IIdentityCredentialStore::STATUS_INVALID_DATA,
-                    "SessionTranscript contains invalid CBOR"));
-        }
-        sessionTranscriptItem = std::move(item);
+    ndk::ScopedAStatus status = ensureHwProxy();
+    if (!status.isOk()) {
+        return status;
     }
+
+    // If in a session, ensure the passed-in session transcript matches the
+    // session transcript from the session.
+    if (session_) {
+        if (sessionTranscript != session_->getSessionTranscript()) {
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    IIdentityCredentialStore::STATUS_SESSION_TRANSCRIPT_MISMATCH,
+                    "In a session and passed-in SessionTranscript doesn't match the one "
+                    "from the session"));
+        }
+    }
+
     if (numStartRetrievalCalls_ > 0) {
         if (sessionTranscript_ != sessionTranscript) {
             LOG(ERROR) << "Session Transcript changed";
@@ -390,32 +456,36 @@
         }
     }
 
-    // TODO: move this check to the TA
-#if 1
-    // To prevent replay-attacks, we check that the public part of the ephemeral
-    // key we previously created, is present in the DeviceEngagement part of
-    // SessionTranscript as a COSE_Key, in uncompressed form.
-    //
-    // We do this by just searching for the X and Y coordinates.
-    if (sessionTranscript.size() > 0) {
-        auto [getXYSuccess, ePubX, ePubY] = support::ecPublicKeyGetXandY(ephemeralPublicKey_);
-        if (!getXYSuccess) {
-            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
-                    IIdentityCredentialStore::STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND,
-                    "Error extracting X and Y from ePub"));
-        }
-        if (sessionTranscript.size() > 0 &&
-            !(memmem(sessionTranscript.data(), sessionTranscript.size(), ePubX.data(),
-                     ePubX.size()) != nullptr &&
-              memmem(sessionTranscript.data(), sessionTranscript.size(), ePubY.data(),
-                     ePubY.size()) != nullptr)) {
-            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
-                    IIdentityCredentialStore::STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND,
-                    "Did not find ephemeral public key's X and Y coordinates in "
-                    "SessionTranscript (make sure leading zeroes are not used)"));
+    if (session_) {
+        // If presenting in a session, the TA has already done this check.
+
+    } else {
+        // To prevent replay-attacks, we check that the public part of the ephemeral
+        // key we previously created, is present in the DeviceEngagement part of
+        // SessionTranscript as a COSE_Key, in uncompressed form.
+        //
+        // We do this by just searching for the X and Y coordinates.
+        //
+        // Would be nice to move this check to the TA.
+        if (sessionTranscript.size() > 0) {
+            auto [getXYSuccess, ePubX, ePubY] = support::ecPublicKeyGetXandY(ephemeralPublicKey_);
+            if (!getXYSuccess) {
+                return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                        IIdentityCredentialStore::STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND,
+                        "Error extracting X and Y from ePub"));
+            }
+            if (sessionTranscript.size() > 0 &&
+                !(memmem(sessionTranscript.data(), sessionTranscript.size(), ePubX.data(),
+                         ePubX.size()) != nullptr &&
+                  memmem(sessionTranscript.data(), sessionTranscript.size(), ePubY.data(),
+                         ePubY.size()) != nullptr)) {
+                return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                        IIdentityCredentialStore::STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND,
+                        "Did not find ephemeral public key's X and Y coordinates in "
+                        "SessionTranscript (make sure leading zeroes are not used)"));
+            }
         }
     }
-#endif
 
     // itemsRequest: If non-empty, contains request data that may be signed by the
     // reader.  The content can be defined in the way appropriate for the
@@ -537,21 +607,38 @@
 
     // Finally, pass info so the HMAC key can be derived and the TA can start
     // creating the DeviceNameSpaces CBOR...
-    if (sessionTranscript_.size() > 0 && readerPublicKey_.size() > 0 && signingKeyBlob.size() > 0) {
-        // We expect the reader ephemeral public key to be same size and curve
-        // as the ephemeral key we generated (e.g. P-256 key), otherwise ECDH
-        // won't work. So its length should be 65 bytes and it should be
-        // starting with 0x04.
-        if (readerPublicKey_.size() != 65 || readerPublicKey_[0] != 0x04) {
-            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
-                    IIdentityCredentialStore::STATUS_FAILED,
-                    "Reader public key is not in expected format"));
+    if (!session_) {
+        if (sessionTranscript_.size() > 0 && readerPublicKey_.size() > 0 &&
+            signingKeyBlob.size() > 0) {
+            // We expect the reader ephemeral public key to be same size and curve
+            // as the ephemeral key we generated (e.g. P-256 key), otherwise ECDH
+            // won't work. So its length should be 65 bytes and it should be
+            // starting with 0x04.
+            if (readerPublicKey_.size() != 65 || readerPublicKey_[0] != 0x04) {
+                return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                        IIdentityCredentialStore::STATUS_FAILED,
+                        "Reader public key is not in expected format"));
+            }
+            vector<uint8_t> pubKeyP256(readerPublicKey_.begin() + 1, readerPublicKey_.end());
+            if (!hwProxy_->calcMacKey(sessionTranscript_, pubKeyP256, signingKeyBlob, docType_,
+                                      numNamespacesWithValues, expectedDeviceNameSpacesSize_)) {
+                return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                        IIdentityCredentialStore::STATUS_FAILED,
+                        "Error starting retrieving entries"));
+            }
         }
-        vector<uint8_t> pubKeyP256(readerPublicKey_.begin() + 1, readerPublicKey_.end());
-        if (!hwProxy_->calcMacKey(sessionTranscript_, pubKeyP256, signingKeyBlob, docType_,
-                                  numNamespacesWithValues, expectedDeviceNameSpacesSize_)) {
-            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
-                    IIdentityCredentialStore::STATUS_FAILED, "Error starting retrieving entries"));
+    } else {
+        if (session_->getSessionTranscript().size() > 0 &&
+            session_->getReaderEphemeralPublicKey().size() > 0 && signingKeyBlob.size() > 0) {
+            // Don't actually pass the reader ephemeral public key in, the TA will get
+            // it from the session object.
+            //
+            if (!hwProxy_->calcMacKey(sessionTranscript_, {}, signingKeyBlob, docType_,
+                                      numNamespacesWithValues, expectedDeviceNameSpacesSize_)) {
+                return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                        IIdentityCredentialStore::STATUS_FAILED,
+                        "Error starting retrieving entries"));
+            }
         }
     }
 
@@ -665,6 +752,11 @@
 ndk::ScopedAStatus IdentityCredential::startRetrieveEntryValue(
         const string& nameSpace, const string& name, int32_t entrySize,
         const vector<int32_t>& accessControlProfileIds) {
+    ndk::ScopedAStatus status = ensureHwProxy();
+    if (!status.isOk()) {
+        return status;
+    }
+
     if (name.empty()) {
         return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
                 IIdentityCredentialStore::STATUS_INVALID_DATA, "Name cannot be empty"));
@@ -785,6 +877,11 @@
 
 ndk::ScopedAStatus IdentityCredential::retrieveEntryValue(const vector<uint8_t>& encryptedContent,
                                                           vector<uint8_t>* outContent) {
+    ndk::ScopedAStatus status = ensureHwProxy();
+    if (!status.isOk()) {
+        return status;
+    }
+
     optional<vector<uint8_t>> content = hwProxy_->retrieveEntryValue(
             encryptedContent, currentNameSpace_, currentName_, currentAccessControlProfileIds_);
     if (!content) {
@@ -829,6 +926,11 @@
 
 ndk::ScopedAStatus IdentityCredential::finishRetrieval(vector<uint8_t>* outMac,
                                                        vector<uint8_t>* outDeviceNameSpaces) {
+    ndk::ScopedAStatus status = ensureHwProxy();
+    if (!status.isOk()) {
+        return status;
+    }
+
     if (currentNameSpaceDeviceNameSpacesMap_.size() > 0) {
         deviceNameSpacesMap_.add(currentNameSpace_,
                                  std::move(currentNameSpaceDeviceNameSpacesMap_));
@@ -846,18 +948,23 @@
                         .c_str()));
     }
 
-    // If there's no signing key or no sessionTranscript or no reader ephemeral
-    // public key, we return the empty MAC.
+    // If the TA calculated a MAC (it might not have), format it as a COSE_Mac0
+    //
     optional<vector<uint8_t>> mac;
-    if (signingKeyBlob_.size() > 0 && sessionTranscript_.size() > 0 &&
-        readerPublicKey_.size() > 0) {
-        optional<vector<uint8_t>> digestToBeMaced = hwProxy_->finishRetrieval();
-        if (!digestToBeMaced || digestToBeMaced.value().size() != 32) {
+    optional<vector<uint8_t>> digestToBeMaced = hwProxy_->finishRetrieval();
+
+    // The MAC not being set means an error occurred.
+    if (!digestToBeMaced) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_INVALID_DATA, "Error generating digestToBeMaced"));
+    }
+    // Size 0 means that the MAC isn't set. If it's set, it has to be 32 bytes.
+    if (digestToBeMaced.value().size() != 0) {
+        if (digestToBeMaced.value().size() != 32) {
             return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
                     IIdentityCredentialStore::STATUS_INVALID_DATA,
-                    "Error generating digestToBeMaced"));
+                    "Unexpected size for digestToBeMaced"));
         }
-        // Now construct COSE_Mac0 from the returned MAC...
         mac = support::coseMacWithDigest(digestToBeMaced.value(), {} /* data */);
     }
 
@@ -868,6 +975,15 @@
 
 ndk::ScopedAStatus IdentityCredential::generateSigningKeyPair(
         vector<uint8_t>* outSigningKeyBlob, Certificate* outSigningKeyCertificate) {
+    if (session_) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED, "Cannot be called in a session"));
+    }
+    ndk::ScopedAStatus status = ensureHwProxy();
+    if (!status.isOk()) {
+        return status;
+    }
+
     time_t now = time(NULL);
     optional<pair<vector<uint8_t>, vector<uint8_t>>> pair =
             hwProxy_->generateSigningKeyPair(docType_, now);
@@ -885,10 +1001,19 @@
 
 ndk::ScopedAStatus IdentityCredential::updateCredential(
         shared_ptr<IWritableIdentityCredential>* outWritableCredential) {
-    sp<SecureHardwareProvisioningProxy> hwProxy = hwProxyFactory_->createProvisioningProxy();
+    if (session_) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED, "Cannot be called in a session"));
+    }
+    sp<SecureHardwareProvisioningProxy> provisioningHwProxy =
+            hwProxyFactory_->createProvisioningProxy();
+    if (!provisioningHwProxy) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED, "Error creating provisioning proxy"));
+    }
     shared_ptr<WritableIdentityCredential> wc =
-            ndk::SharedRefBase::make<WritableIdentityCredential>(hwProxy, docType_,
-                                                                 testCredential_);
+            ndk::SharedRefBase::make<WritableIdentityCredential>(
+                    provisioningHwProxy, docType_, testCredential_, hardwareInformation_);
     if (!wc->initializeForUpdate(encryptedCredentialKeys_)) {
         return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
                 IIdentityCredentialStore::STATUS_FAILED,
diff --git a/identity/aidl/default/common/IdentityCredential.h b/identity/aidl/default/common/IdentityCredential.h
index ef9d133..5929829 100644
--- a/identity/aidl/default/common/IdentityCredential.h
+++ b/identity/aidl/default/common/IdentityCredential.h
@@ -30,6 +30,7 @@
 #include <cppbor.h>
 
 #include "IdentityCredentialStore.h"
+#include "PresentationSession.h"
 #include "SecureHardwareProxy.h"
 
 namespace aidl::android::hardware::identity {
@@ -46,12 +47,14 @@
 class IdentityCredential : public BnIdentityCredential {
   public:
     IdentityCredential(sp<SecureHardwareProxyFactory> hwProxyFactory,
-                       sp<SecureHardwarePresentationProxy> hwProxy,
-                       const vector<uint8_t>& credentialData)
+                       const vector<uint8_t>& credentialData,
+                       std::shared_ptr<PresentationSession> session,
+                       HardwareInformation hardwareInformation)
         : hwProxyFactory_(hwProxyFactory),
-          hwProxy_(hwProxy),
           credentialData_(credentialData),
+          session_(std::move(session)),
           numStartRetrievalCalls_(0),
+          hardwareInformation_(std::move(hardwareInformation)),
           expectedDeviceNameSpacesSize_(0) {}
 
     // Parses and decrypts credentialData_, return a status code from
@@ -94,17 +97,24 @@
                                               bool includeChallenge,
                                               vector<uint8_t>* outProofOfDeletionSignature);
 
+    // Creates and initializes hwProxy_.
+    ndk::ScopedAStatus ensureHwProxy();
+
     // Set by constructor
     sp<SecureHardwareProxyFactory> hwProxyFactory_;
-    sp<SecureHardwarePresentationProxy> hwProxy_;
     vector<uint8_t> credentialData_;
+    shared_ptr<PresentationSession> session_;
     int numStartRetrievalCalls_;
+    HardwareInformation hardwareInformation_;
 
     // Set by initialize()
     string docType_;
     bool testCredential_;
     vector<uint8_t> encryptedCredentialKeys_;
 
+    // Set by ensureHwProxy()
+    sp<SecureHardwarePresentationProxy> hwProxy_;
+
     // Set by createEphemeralKeyPair()
     vector<uint8_t> ephemeralPublicKey_;
 
diff --git a/identity/aidl/default/common/IdentityCredentialStore.cpp b/identity/aidl/default/common/IdentityCredentialStore.cpp
index e6b5466..bbc2cef 100644
--- a/identity/aidl/default/common/IdentityCredentialStore.cpp
+++ b/identity/aidl/default/common/IdentityCredentialStore.cpp
@@ -17,22 +17,33 @@
 #define LOG_TAG "IdentityCredentialStore"
 
 #include <android-base/logging.h>
+#include <android/binder_manager.h>
 
 #include "IdentityCredential.h"
 #include "IdentityCredentialStore.h"
+#include "PresentationSession.h"
 #include "WritableIdentityCredential.h"
 
 namespace aidl::android::hardware::identity {
 
+using ::aidl::android::hardware::security::keymint::IRemotelyProvisionedComponent;
+
+IdentityCredentialStore::IdentityCredentialStore(sp<SecureHardwareProxyFactory> hwProxyFactory,
+                                                 optional<string> remotelyProvisionedComponent)
+    : hwProxyFactory_(hwProxyFactory),
+      remotelyProvisionedComponentName_(remotelyProvisionedComponent) {
+    hardwareInformation_.credentialStoreName = "Identity Credential Reference Implementation";
+    hardwareInformation_.credentialStoreAuthorName = "Google";
+    hardwareInformation_.dataChunkSize = kGcmChunkSize;
+    hardwareInformation_.isDirectAccess = false;
+    hardwareInformation_.supportedDocTypes = {};
+    hardwareInformation_.isRemoteKeyProvisioningSupported =
+            remotelyProvisionedComponentName_.has_value();
+}
+
 ndk::ScopedAStatus IdentityCredentialStore::getHardwareInformation(
         HardwareInformation* hardwareInformation) {
-    HardwareInformation hw;
-    hw.credentialStoreName = "Identity Credential Reference Implementation";
-    hw.credentialStoreAuthorName = "Google";
-    hw.dataChunkSize = kGcmChunkSize;
-    hw.isDirectAccess = false;
-    hw.supportedDocTypes = {};
-    *hardwareInformation = hw;
+    *hardwareInformation = hardwareInformation_;
     return ndk::ScopedAStatus::ok();
 }
 
@@ -41,7 +52,8 @@
         shared_ptr<IWritableIdentityCredential>* outWritableCredential) {
     sp<SecureHardwareProvisioningProxy> hwProxy = hwProxyFactory_->createProvisioningProxy();
     shared_ptr<WritableIdentityCredential> wc =
-            ndk::SharedRefBase::make<WritableIdentityCredential>(hwProxy, docType, testCredential);
+            ndk::SharedRefBase::make<WritableIdentityCredential>(hwProxy, docType, testCredential,
+                                                                 hardwareInformation_);
     if (!wc->initialize()) {
         return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
                 IIdentityCredentialStore::STATUS_FAILED,
@@ -61,9 +73,8 @@
                 "Unsupported cipher suite"));
     }
 
-    sp<SecureHardwarePresentationProxy> hwProxy = hwProxyFactory_->createPresentationProxy();
-    shared_ptr<IdentityCredential> credential =
-            ndk::SharedRefBase::make<IdentityCredential>(hwProxyFactory_, hwProxy, credentialData);
+    shared_ptr<IdentityCredential> credential = ndk::SharedRefBase::make<IdentityCredential>(
+            hwProxyFactory_, credentialData, nullptr /* session */, hardwareInformation_);
     auto ret = credential->initialize();
     if (ret != IIdentityCredentialStore::STATUS_OK) {
         return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
@@ -73,4 +84,44 @@
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus IdentityCredentialStore::createPresentationSession(
+        CipherSuite cipherSuite, shared_ptr<IPresentationSession>* outSession) {
+    // We only support CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256 right now.
+    if (cipherSuite != CipherSuite::CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_CIPHER_SUITE_NOT_SUPPORTED,
+                "Unsupported cipher suite"));
+    }
+
+    sp<SecureHardwareSessionProxy> hwProxy = hwProxyFactory_->createSessionProxy();
+    shared_ptr<PresentationSession> session = ndk::SharedRefBase::make<PresentationSession>(
+            hwProxyFactory_, hwProxy, hardwareInformation_);
+    auto ret = session->initialize();
+    if (ret != IIdentityCredentialStore::STATUS_OK) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                int(ret), "Error initializing PresentationSession"));
+    }
+    *outSession = session;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus IdentityCredentialStore::getRemotelyProvisionedComponent(
+        shared_ptr<IRemotelyProvisionedComponent>* outRemotelyProvisionedComponent) {
+    if (!remotelyProvisionedComponentName_) {
+        return ndk::ScopedAStatus(AStatus_fromExceptionCodeWithMessage(
+                EX_UNSUPPORTED_OPERATION, "Remote key provisioning is not supported"));
+    }
+
+    ndk::SpAIBinder binder(
+            AServiceManager_waitForService(remotelyProvisionedComponentName_->c_str()));
+    if (binder.get() == nullptr) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED,
+                "Unable to get remotely provisioned component"));
+    }
+
+    *outRemotelyProvisionedComponent = IRemotelyProvisionedComponent::fromBinder(binder);
+    return ndk::ScopedAStatus::ok();
+}
+
 }  // namespace aidl::android::hardware::identity
diff --git a/identity/aidl/default/common/IdentityCredentialStore.h b/identity/aidl/default/common/IdentityCredentialStore.h
index d35e632..dd1261b 100644
--- a/identity/aidl/default/common/IdentityCredentialStore.h
+++ b/identity/aidl/default/common/IdentityCredentialStore.h
@@ -18,6 +18,7 @@
 #define ANDROID_HARDWARE_IDENTITY_IDENTITYCREDENTIALSTORE_H
 
 #include <aidl/android/hardware/identity/BnIdentityCredentialStore.h>
+#include <aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.h>
 
 #include "SecureHardwareProxy.h"
 
@@ -25,14 +26,18 @@
 
 using ::android::sp;
 using ::android::hardware::identity::SecureHardwareProxyFactory;
+using ::std::optional;
 using ::std::shared_ptr;
 using ::std::string;
 using ::std::vector;
 
 class IdentityCredentialStore : public BnIdentityCredentialStore {
   public:
-    IdentityCredentialStore(sp<SecureHardwareProxyFactory> hwProxyFactory)
-        : hwProxyFactory_(hwProxyFactory) {}
+    // If remote key provisioning is supported, pass the service name for the correct
+    // IRemotelyProvisionedComponent to the remotelyProvisionedComponent parameter. Else
+    // pass std::nullopt to indicate remote key provisioning is not supported.
+    IdentityCredentialStore(sp<SecureHardwareProxyFactory> hwProxyFactory,
+                            optional<string> remotelyProvisionedComponent);
 
     // The GCM chunk size used by this implementation is 64 KiB.
     static constexpr size_t kGcmChunkSize = 64 * 1024;
@@ -47,8 +52,17 @@
     ndk::ScopedAStatus getCredential(CipherSuite cipherSuite, const vector<uint8_t>& credentialData,
                                      shared_ptr<IIdentityCredential>* outCredential) override;
 
+    ndk::ScopedAStatus createPresentationSession(
+            CipherSuite cipherSuite, shared_ptr<IPresentationSession>* outSession) override;
+
+    ndk::ScopedAStatus getRemotelyProvisionedComponent(
+            shared_ptr<::aidl::android::hardware::security::keymint::IRemotelyProvisionedComponent>*
+                    outRemotelyProvisionedComponent) override;
+
   private:
     sp<SecureHardwareProxyFactory> hwProxyFactory_;
+    optional<string> remotelyProvisionedComponentName_;
+    HardwareInformation hardwareInformation_;
 };
 
 }  // namespace aidl::android::hardware::identity
diff --git a/identity/aidl/default/common/PresentationSession.cpp b/identity/aidl/default/common/PresentationSession.cpp
new file mode 100644
index 0000000..2eb7f2e
--- /dev/null
+++ b/identity/aidl/default/common/PresentationSession.cpp
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "PresentationSession"
+
+#include "PresentationSession.h"
+#include "IdentityCredentialStore.h"
+
+#include <android/hardware/identity/support/IdentityCredentialSupport.h>
+
+#include <string.h>
+
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+
+#include <cppbor.h>
+#include <cppbor_parse.h>
+
+#include "FakeSecureHardwareProxy.h"
+#include "IdentityCredential.h"
+#include "PresentationSession.h"
+
+namespace aidl::android::hardware::identity {
+
+using ::std::optional;
+
+using namespace ::android::hardware::identity;
+
+PresentationSession::~PresentationSession() {}
+
+int PresentationSession::initialize() {
+    if (!hwProxy_->initialize()) {
+        LOG(ERROR) << "hwProxy->initialize failed";
+        return IIdentityCredentialStore::STATUS_FAILED;
+    }
+
+    optional<uint64_t> id = hwProxy_->getId();
+    if (!id) {
+        LOG(ERROR) << "Error getting id for session";
+        return IIdentityCredentialStore::STATUS_FAILED;
+    }
+    id_ = id.value();
+
+    optional<vector<uint8_t>> ephemeralKeyPriv = hwProxy_->getEphemeralKeyPair();
+    if (!ephemeralKeyPriv) {
+        LOG(ERROR) << "Error getting ephemeral private key for session";
+        return IIdentityCredentialStore::STATUS_FAILED;
+    }
+    optional<vector<uint8_t>> ephemeralKeyPair =
+            support::ecPrivateKeyToKeyPair(ephemeralKeyPriv.value());
+    if (!ephemeralKeyPair) {
+        LOG(ERROR) << "Error creating ephemeral key-pair";
+        return IIdentityCredentialStore::STATUS_FAILED;
+    }
+    ephemeralKeyPair_ = ephemeralKeyPair.value();
+
+    optional<uint64_t> authChallenge = hwProxy_->getAuthChallenge();
+    if (!authChallenge) {
+        LOG(ERROR) << "Error getting authChallenge for session";
+        return IIdentityCredentialStore::STATUS_FAILED;
+    }
+    authChallenge_ = authChallenge.value();
+
+    return IIdentityCredentialStore::STATUS_OK;
+}
+
+ndk::ScopedAStatus PresentationSession::getEphemeralKeyPair(vector<uint8_t>* outKeyPair) {
+    *outKeyPair = ephemeralKeyPair_;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus PresentationSession::getAuthChallenge(int64_t* outChallenge) {
+    *outChallenge = authChallenge_;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus PresentationSession::setReaderEphemeralPublicKey(
+        const vector<uint8_t>& publicKey) {
+    // We expect the reader ephemeral public key to be same size and curve
+    // as the ephemeral key we generated (e.g. P-256 key), otherwise ECDH
+    // won't work. So its length should be 65 bytes and it should be
+    // starting with 0x04.
+    if (publicKey.size() != 65 || publicKey[0] != 0x04) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED,
+                "Reader public key is not in expected format"));
+    }
+    readerPublicKey_ = publicKey;
+    vector<uint8_t> pubKeyP256(publicKey.begin() + 1, publicKey.end());
+    if (!hwProxy_->setReaderEphemeralPublicKey(pubKeyP256)) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED,
+                "Error setting readerEphemeralPublicKey for session"));
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus PresentationSession::setSessionTranscript(
+        const vector<uint8_t>& sessionTranscript) {
+    sessionTranscript_ = sessionTranscript;
+    if (!hwProxy_->setSessionTranscript(sessionTranscript)) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED,
+                "Error setting SessionTranscript for session"));
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus PresentationSession::getCredential(
+        const vector<uint8_t>& credentialData, shared_ptr<IIdentityCredential>* outCredential) {
+    shared_ptr<PresentationSession> p = ref<PresentationSession>();
+    shared_ptr<IdentityCredential> credential = ndk::SharedRefBase::make<IdentityCredential>(
+            hwProxyFactory_, credentialData, p, hardwareInformation_);
+    int ret = credential->initialize();
+    if (ret != IIdentityCredentialStore::STATUS_OK) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                ret, "Error initializing IdentityCredential"));
+    }
+    *outCredential = std::move(credential);
+
+    return ndk::ScopedAStatus::ok();
+}
+
+uint64_t PresentationSession::getSessionId() {
+    return id_;
+}
+
+vector<uint8_t> PresentationSession::getSessionTranscript() {
+    return sessionTranscript_;
+}
+
+vector<uint8_t> PresentationSession::getReaderEphemeralPublicKey() {
+    return readerPublicKey_;
+}
+
+}  // namespace aidl::android::hardware::identity
diff --git a/identity/aidl/default/common/PresentationSession.h b/identity/aidl/default/common/PresentationSession.h
new file mode 100644
index 0000000..4cb174a
--- /dev/null
+++ b/identity/aidl/default/common/PresentationSession.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_IDENTITY_PRESENTATIONSESSION_H
+#define ANDROID_HARDWARE_IDENTITY_PRESENTATIONSESSION_H
+
+#include <aidl/android/hardware/identity/BnPresentationSession.h>
+#include <android/hardware/identity/support/IdentityCredentialSupport.h>
+
+#include <vector>
+
+#include <cppbor.h>
+
+#include "IdentityCredentialStore.h"
+#include "SecureHardwareProxy.h"
+
+namespace aidl::android::hardware::identity {
+
+using ::aidl::android::hardware::keymaster::HardwareAuthToken;
+using ::aidl::android::hardware::keymaster::VerificationToken;
+using ::android::sp;
+using ::android::hardware::identity::SecureHardwareSessionProxy;
+using ::std::vector;
+
+class PresentationSession : public BnPresentationSession {
+  public:
+    PresentationSession(sp<SecureHardwareProxyFactory> hwProxyFactory,
+                        sp<SecureHardwareSessionProxy> hwProxy,
+                        HardwareInformation hardwareInformation)
+        : hwProxyFactory_(std::move(hwProxyFactory)),
+          hwProxy_(std::move(hwProxy)),
+          hardwareInformation_(std::move(hardwareInformation)) {}
+
+    virtual ~PresentationSession();
+
+    // Creates ephemeral key and auth-challenge in TA. Returns a status code from
+    // IIdentityCredentialStore. Must be called right after construction.
+    int initialize();
+
+    uint64_t getSessionId();
+
+    vector<uint8_t> getSessionTranscript();
+    vector<uint8_t> getReaderEphemeralPublicKey();
+
+    // Methods from IPresentationSession follow.
+    ndk::ScopedAStatus getEphemeralKeyPair(vector<uint8_t>* outKeyPair) override;
+    ndk::ScopedAStatus getAuthChallenge(int64_t* outChallenge) override;
+    ndk::ScopedAStatus setReaderEphemeralPublicKey(const vector<uint8_t>& publicKey) override;
+    ndk::ScopedAStatus setSessionTranscript(const vector<uint8_t>& sessionTranscript) override;
+
+    ndk::ScopedAStatus getCredential(const vector<uint8_t>& credentialData,
+                                     shared_ptr<IIdentityCredential>* outCredential) override;
+
+  private:
+    // Set by constructor
+    sp<SecureHardwareProxyFactory> hwProxyFactory_;
+    sp<SecureHardwareSessionProxy> hwProxy_;
+    HardwareInformation hardwareInformation_;
+
+    // Set by initialize()
+    uint64_t id_;
+    vector<uint8_t> ephemeralKeyPair_;
+    uint64_t authChallenge_;
+
+    // Set by setReaderEphemeralPublicKey()
+    vector<uint8_t> readerPublicKey_;
+
+    // Set by setSessionTranscript()
+    vector<uint8_t> sessionTranscript_;
+};
+
+}  // namespace aidl::android::hardware::identity
+
+#endif  // ANDROID_HARDWARE_IDENTITY_PRESENTATIONSESSION_H
diff --git a/identity/aidl/default/common/SecureHardwareProxy.h b/identity/aidl/default/common/SecureHardwareProxy.h
index a1ed1ef..9f63ad8 100644
--- a/identity/aidl/default/common/SecureHardwareProxy.h
+++ b/identity/aidl/default/common/SecureHardwareProxy.h
@@ -42,6 +42,7 @@
 // Forward declare.
 //
 class SecureHardwareProvisioningProxy;
+class SecureHardwareSessionProxy;
 class SecureHardwarePresentationProxy;
 
 // This is a class used to create proxies.
@@ -52,6 +53,7 @@
     virtual ~SecureHardwareProxyFactory() {}
 
     virtual sp<SecureHardwareProvisioningProxy> createProvisioningProxy() = 0;
+    virtual sp<SecureHardwareSessionProxy> createSessionProxy() = 0;
     virtual sp<SecureHardwarePresentationProxy> createPresentationProxy() = 0;
 };
 
@@ -64,8 +66,12 @@
 
     virtual bool initialize(bool testCredential) = 0;
 
-    virtual bool initializeForUpdate(bool testCredential, string docType,
-                                     vector<uint8_t> encryptedCredentialKeys) = 0;
+    virtual bool initializeForUpdate(bool testCredential, const string& docType,
+                                     const vector<uint8_t>& encryptedCredentialKeys) = 0;
+
+    virtual optional<uint32_t> getId() = 0;
+
+    virtual bool shutdown() = 0;
 
     // Returns public key certificate chain with attestation.
     //
@@ -76,7 +82,19 @@
     virtual optional<vector<uint8_t>> createCredentialKey(const vector<uint8_t>& challenge,
                                                           const vector<uint8_t>& applicationId) = 0;
 
-    virtual bool startPersonalization(int accessControlProfileCount, vector<int> entryCounts,
+    // Returns public key certificate with a remotely provisioned attestation key.
+    //
+    // This returns a single certificate that is signed by the given |attestationKeyBlob|.
+    // The implementation of eicOpsCreateCredentialKey() on the TA side must coordinate
+    // with its corresponding keymint implementation to sign using the attestation key. The
+    // |attestationKeyCert| parameter is the certificates for |attestationKeyBlob|,
+    // formatted as concatenated, DER-encoded, X.509 certificates.
+    virtual optional<vector<uint8_t>> createCredentialKeyUsingRkp(
+            const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId,
+            const vector<uint8_t>& attestationKeyBlob,
+            const vector<uint8_t>& attestationKeyCert) = 0;
+
+    virtual bool startPersonalization(int accessControlProfileCount, const vector<int>& entryCounts,
                                       const string& docType,
                                       size_t expectedProofOfProvisioningSize) = 0;
 
@@ -98,8 +116,6 @@
 
     // Returns encryptedCredentialKeys (80 bytes).
     virtual optional<vector<uint8_t>> finishGetCredentialData(const string& docType) = 0;
-
-    virtual bool shutdown() = 0;
 };
 
 enum AccessCheckResult {
@@ -110,6 +126,30 @@
     kReaderAuthenticationFailed,
 };
 
+// The proxy used for sessions.
+//
+class SecureHardwareSessionProxy : public RefBase {
+  public:
+    SecureHardwareSessionProxy() {}
+
+    virtual ~SecureHardwareSessionProxy() {}
+
+    virtual bool initialize() = 0;
+
+    virtual optional<uint32_t> getId() = 0;
+
+    virtual bool shutdown() = 0;
+
+    virtual optional<uint64_t> getAuthChallenge() = 0;
+
+    // Returns private key
+    virtual optional<vector<uint8_t>> getEphemeralKeyPair() = 0;
+
+    virtual bool setReaderEphemeralPublicKey(const vector<uint8_t>& readerEphemeralPublicKey) = 0;
+
+    virtual bool setSessionTranscript(const vector<uint8_t>& sessionTranscript) = 0;
+};
+
 // The proxy used for presentation.
 //
 class SecureHardwarePresentationProxy : public RefBase {
@@ -117,12 +157,16 @@
     SecureHardwarePresentationProxy() {}
     virtual ~SecureHardwarePresentationProxy() {}
 
-    virtual bool initialize(bool testCredential, string docType,
-                            vector<uint8_t> encryptedCredentialKeys) = 0;
+    virtual bool initialize(uint32_t sessionId, bool testCredential, const string& docType,
+                            const vector<uint8_t>& encryptedCredentialKeys) = 0;
+
+    virtual optional<uint32_t> getId() = 0;
+
+    virtual bool shutdown() = 0;
 
     // Returns publicKeyCert (1st component) and signingKeyBlob (2nd component)
-    virtual optional<pair<vector<uint8_t>, vector<uint8_t>>> generateSigningKeyPair(string docType,
-                                                                                    time_t now) = 0;
+    virtual optional<pair<vector<uint8_t>, vector<uint8_t>>> generateSigningKeyPair(
+            const string& docType, time_t now) = 0;
 
     // Returns private key
     virtual optional<vector<uint8_t>> createEphemeralKeyPair() = 0;
@@ -174,8 +218,6 @@
     virtual optional<vector<uint8_t>> proveOwnership(const string& docType, bool testCredential,
                                                      const vector<uint8_t>& challenge,
                                                      size_t proofOfOwnershipCborSize) = 0;
-
-    virtual bool shutdown() = 0;
 };
 
 }  // namespace android::hardware::identity
diff --git a/identity/aidl/default/common/WritableIdentityCredential.cpp b/identity/aidl/default/common/WritableIdentityCredential.cpp
index 200ee61..e420a7b 100644
--- a/identity/aidl/default/common/WritableIdentityCredential.cpp
+++ b/identity/aidl/default/common/WritableIdentityCredential.cpp
@@ -79,8 +79,15 @@
                 IIdentityCredentialStore::STATUS_INVALID_DATA, "Challenge can not be empty"));
     }
 
-    optional<vector<uint8_t>> certChain =
-            hwProxy_->createCredentialKey(attestationChallenge, attestationApplicationId);
+    optional<vector<uint8_t>> certChain;
+    if (attestationKeyBlob_ && attestationCertificateChain_) {
+        certChain = hwProxy_->createCredentialKeyUsingRkp(
+                attestationChallenge, attestationApplicationId, *attestationKeyBlob_,
+                attestationCertificateChain_->at(0));
+    } else {
+        certChain = hwProxy_->createCredentialKey(attestationChallenge, attestationApplicationId);
+    }
+
     if (!certChain) {
         return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
                 IIdentityCredentialStore::STATUS_FAILED,
@@ -95,8 +102,14 @@
     }
 
     *outCertificateChain = vector<Certificate>();
-    for (const vector<uint8_t>& cert : certs.value()) {
-        Certificate c = Certificate();
+    for (vector<uint8_t>& cert : certs.value()) {
+        Certificate c;
+        c.encodedCertificate = std::move(cert);
+        outCertificateChain->push_back(std::move(c));
+    }
+
+    for (const vector<uint8_t>& cert : *attestationCertificateChain_) {
+        Certificate c;
         c.encodedCertificate = cert;
         outCertificateChain->push_back(std::move(c));
     }
@@ -402,4 +415,36 @@
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus WritableIdentityCredential::setRemotelyProvisionedAttestationKey(
+        const vector<uint8_t>& attestationKeyBlob,
+        const vector<uint8_t>& attestationCertificateChain) {
+    if (!hardwareInformation_.isRemoteKeyProvisioningSupported) {
+        return ndk::ScopedAStatus(AStatus_fromExceptionCodeWithMessage(
+                EX_UNSUPPORTED_OPERATION, "Remote key provisioning is not supported"));
+    }
+
+    if (attestationKeyBlob.empty() || attestationCertificateChain.empty()) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED,
+                "Empty data passed to setRemotlyProvisionedAttestationKey"));
+    }
+
+    if (attestationKeyBlob_.has_value()) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED, "Attestation key already set"));
+    }
+
+    optional<vector<vector<uint8_t>>> certs =
+            support::certificateChainSplit(attestationCertificateChain);
+    if (!certs) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED,
+                "Error splitting chain into separate certificates"));
+    }
+
+    attestationKeyBlob_ = attestationKeyBlob;
+    attestationCertificateChain_ = *certs;
+    return ndk::ScopedAStatus::ok();
+}
+
 }  // namespace aidl::android::hardware::identity
diff --git a/identity/aidl/default/common/WritableIdentityCredential.h b/identity/aidl/default/common/WritableIdentityCredential.h
index 36ad430..39d32c9 100644
--- a/identity/aidl/default/common/WritableIdentityCredential.h
+++ b/identity/aidl/default/common/WritableIdentityCredential.h
@@ -30,6 +30,7 @@
 
 using ::android::sp;
 using ::android::hardware::identity::SecureHardwareProvisioningProxy;
+using ::std::optional;
 using ::std::set;
 using ::std::string;
 using ::std::vector;
@@ -41,8 +42,11 @@
     // For an updated credential, call initializeForUpdate() right after construction.
     //
     WritableIdentityCredential(sp<SecureHardwareProvisioningProxy> hwProxy, const string& docType,
-                               bool testCredential)
-        : hwProxy_(hwProxy), docType_(docType), testCredential_(testCredential) {}
+                               bool testCredential, HardwareInformation hardwareInformation)
+        : hwProxy_(hwProxy),
+          docType_(docType),
+          testCredential_(testCredential),
+          hardwareInformation_(std::move(hardwareInformation)) {}
 
     ~WritableIdentityCredential();
 
@@ -78,11 +82,16 @@
             vector<uint8_t>* outCredentialData,
             vector<uint8_t>* outProofOfProvisioningSignature) override;
 
+    ndk::ScopedAStatus setRemotelyProvisionedAttestationKey(
+            const vector<uint8_t>& attestationKeyBlob,
+            const vector<uint8_t>& attestationCertificateChain) override;
+
   private:
     // Set by constructor.
     sp<SecureHardwareProvisioningProxy> hwProxy_;
     string docType_;
     bool testCredential_;
+    HardwareInformation hardwareInformation_;
 
     // This is set in initialize().
     bool startPersonalizationCalled_;
@@ -109,6 +118,10 @@
     vector<int32_t> entryAccessControlProfileIds_;
     vector<uint8_t> entryBytes_;
     set<string> allNameSpaces_;
+
+    // Remotely provisioned attestation data, set via setRemotelyProvisionedAttestationKey
+    optional<vector<uint8_t>> attestationKeyBlob_;
+    optional<vector<vector<uint8_t>>> attestationCertificateChain_;
 };
 
 }  // namespace aidl::android::hardware::identity
diff --git a/identity/aidl/default/identity-default.xml b/identity/aidl/default/identity-default.xml
index a074250..cc0ddc7 100644
--- a/identity/aidl/default/identity-default.xml
+++ b/identity/aidl/default/identity-default.xml
@@ -1,7 +1,7 @@
 <manifest version="1.0" type="device">
     <hal format="aidl">
         <name>android.hardware.identity</name>
-        <version>3</version>
+        <version>4</version>
         <interface>
             <name>IIdentityCredentialStore</name>
             <instance>default</instance>
diff --git a/identity/aidl/default/libeic/EicCbor.c b/identity/aidl/default/libeic/EicCbor.c
index 0e2684f..b9304bc 100644
--- a/identity/aidl/default/libeic/EicCbor.c
+++ b/identity/aidl/default/libeic/EicCbor.c
@@ -91,7 +91,7 @@
     return 8;
 }
 
-void eicCborBegin(EicCbor* cbor, int majorType, size_t size) {
+void eicCborBegin(EicCbor* cbor, int majorType, uint64_t size) {
     uint8_t data[9];
 
     if (size < 24) {
@@ -132,10 +132,13 @@
     eicCborAppend(cbor, data, dataSize);
 }
 
-void eicCborAppendString(EicCbor* cbor, const char* str) {
-    size_t length = eicStrLen(str);
-    eicCborBegin(cbor, EIC_CBOR_MAJOR_TYPE_STRING, length);
-    eicCborAppend(cbor, (const uint8_t*)str, length);
+void eicCborAppendString(EicCbor* cbor, const char* str, size_t strLength) {
+    eicCborBegin(cbor, EIC_CBOR_MAJOR_TYPE_STRING, strLength);
+    eicCborAppend(cbor, (const uint8_t*)str, strLength);
+}
+
+void eicCborAppendStringZ(EicCbor* cbor, const char* str) {
+    eicCborAppendString(cbor, str, eicStrLen(str));
 }
 
 void eicCborAppendSimple(EicCbor* cbor, uint8_t simpleValue) {
@@ -153,13 +156,13 @@
 }
 
 void eicCborAppendUnsigned(EicCbor* cbor, uint64_t value) {
-    size_t encoded = value;
+    uint64_t encoded = value;
     eicCborBegin(cbor, EIC_CBOR_MAJOR_TYPE_UNSIGNED, encoded);
 }
 
 void eicCborAppendNumber(EicCbor* cbor, int64_t value) {
     if (value < 0) {
-        size_t encoded = -1 - value;
+        uint64_t encoded = -1 - value;
         eicCborBegin(cbor, EIC_CBOR_MAJOR_TYPE_NEGATIVE, encoded);
     } else {
         eicCborAppendUnsigned(cbor, value);
@@ -188,19 +191,19 @@
         }
     }
     eicCborAppendMap(cborBuilder, numPairs);
-    eicCborAppendString(cborBuilder, "id");
+    eicCborAppendStringZ(cborBuilder, "id");
     eicCborAppendUnsigned(cborBuilder, id);
     if (readerCertificateSize > 0) {
-        eicCborAppendString(cborBuilder, "readerCertificate");
+        eicCborAppendStringZ(cborBuilder, "readerCertificate");
         eicCborAppendByteString(cborBuilder, readerCertificate, readerCertificateSize);
     }
     if (userAuthenticationRequired) {
-        eicCborAppendString(cborBuilder, "userAuthenticationRequired");
+        eicCborAppendStringZ(cborBuilder, "userAuthenticationRequired");
         eicCborAppendBool(cborBuilder, userAuthenticationRequired);
-        eicCborAppendString(cborBuilder, "timeoutMillis");
+        eicCborAppendStringZ(cborBuilder, "timeoutMillis");
         eicCborAppendUnsigned(cborBuilder, timeoutMillis);
         if (secureUserId > 0) {
-            eicCborAppendString(cborBuilder, "secureUserId");
+            eicCborAppendStringZ(cborBuilder, "secureUserId");
             eicCborAppendUnsigned(cborBuilder, secureUserId);
         }
     }
@@ -214,20 +217,21 @@
     return true;
 }
 
-bool eicCborCalcEntryAdditionalData(const int* accessControlProfileIds,
+bool eicCborCalcEntryAdditionalData(const uint8_t* accessControlProfileIds,
                                     size_t numAccessControlProfileIds, const char* nameSpace,
-                                    const char* name, uint8_t* cborBuffer, size_t cborBufferSize,
-                                    size_t* outAdditionalDataCborSize,
+                                    size_t nameSpaceLength, const char* name,
+                                    size_t nameLength, uint8_t* cborBuffer,
+                                    size_t cborBufferSize, size_t* outAdditionalDataCborSize,
                                     uint8_t additionalDataSha256[EIC_SHA256_DIGEST_SIZE]) {
     EicCbor cborBuilder;
 
     eicCborInit(&cborBuilder, cborBuffer, cborBufferSize);
     eicCborAppendMap(&cborBuilder, 3);
-    eicCborAppendString(&cborBuilder, "Namespace");
-    eicCborAppendString(&cborBuilder, nameSpace);
-    eicCborAppendString(&cborBuilder, "Name");
-    eicCborAppendString(&cborBuilder, name);
-    eicCborAppendString(&cborBuilder, "AccessControlProfileIds");
+    eicCborAppendStringZ(&cborBuilder, "Namespace");
+    eicCborAppendString(&cborBuilder, nameSpace, nameSpaceLength);
+    eicCborAppendStringZ(&cborBuilder, "Name");
+    eicCborAppendString(&cborBuilder, name, nameLength);
+    eicCborAppendStringZ(&cborBuilder, "AccessControlProfileIds");
     eicCborAppendArray(&cborBuilder, numAccessControlProfileIds);
     for (size_t n = 0; n < numAccessControlProfileIds; n++) {
         eicCborAppendNumber(&cborBuilder, accessControlProfileIds[n]);
diff --git a/identity/aidl/default/libeic/EicCbor.h b/identity/aidl/default/libeic/EicCbor.h
index 9c0f531..16f7ab6 100644
--- a/identity/aidl/default/libeic/EicCbor.h
+++ b/identity/aidl/default/libeic/EicCbor.h
@@ -102,13 +102,16 @@
 #define EIC_CBOR_SEMANTIC_TAG_ENCODED_CBOR 24
 
 /* Begins a new CBOR value. */
-void eicCborBegin(EicCbor* cbor, int majorType, size_t size);
+void eicCborBegin(EicCbor* cbor, int majorType, uint64_t size);
 
 /* Appends a bytestring. */
 void eicCborAppendByteString(EicCbor* cbor, const uint8_t* data, size_t dataSize);
 
+/* Appends a UTF-8 string. */
+void eicCborAppendString(EicCbor* cbor, const char* str, size_t strLength);
+
 /* Appends a NUL-terminated UTF-8 string. */
-void eicCborAppendString(EicCbor* cbor, const char* str);
+void eicCborAppendStringZ(EicCbor* cbor, const char* str);
 
 /* Appends a simple value. */
 void eicCborAppendSimple(EicCbor* cbor, uint8_t simpleValue);
@@ -144,22 +147,13 @@
                               size_t readerCertificateSize, bool userAuthenticationRequired,
                               uint64_t timeoutMillis, uint64_t secureUserId);
 
-bool eicCborCalcEntryAdditionalData(const int* accessControlProfileIds,
+bool eicCborCalcEntryAdditionalData(const uint8_t* accessControlProfileIds,
                                     size_t numAccessControlProfileIds, const char* nameSpace,
-                                    const char* name, uint8_t* cborBuffer, size_t cborBufferSize,
-                                    size_t* outAdditionalDataCborSize,
+                                    size_t nameSpaceLength, const char* name,
+                                    size_t nameLength, uint8_t* cborBuffer,
+                                    size_t cborBufferSize, size_t* outAdditionalDataCborSize,
                                     uint8_t additionalDataSha256[EIC_SHA256_DIGEST_SIZE]);
 
-// The maximum size of an encoded Secure Access Control Profile that we
-// support. Since the SACP may contain a reader certificate chain these can get
-// pretty big.
-//
-// Currently we allocate space on the stack for this structure which is why we
-// have a maximum size. We can get rid of the maximum size by incrementally
-// building/verifying the SACP. TODO: actually do this.
-//
-#define EIC_MAX_CBOR_SIZE_FOR_ACCESS_CONTROL_PROFILE 512
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/identity/aidl/default/libeic/EicCommon.h b/identity/aidl/default/libeic/EicCommon.h
new file mode 100644
index 0000000..2a08a35
--- /dev/null
+++ b/identity/aidl/default/libeic/EicCommon.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if !defined(EIC_INSIDE_LIBEIC_H) && !defined(EIC_COMPILATION)
+#error "Never include this file directly, include libeic.h instead."
+#endif
+
+#ifndef ANDROID_HARDWARE_IDENTITY_EIC_COMMON_H
+#define ANDROID_HARDWARE_IDENTITY_EIC_COMMON_H
+
+// KeyMint auth-challenges are 64-bit numbers and 0 typically means unset.
+#define EIC_KM_AUTH_CHALLENGE_UNSET 0
+
+// Feature version 202009:
+//
+//         CredentialKeys = [
+//              bstr,   ; storageKey, a 128-bit AES key
+//              bstr,   ; credentialPrivKey, the private key for credentialKey
+//         ]
+//
+// Feature version 202101:
+//
+//         CredentialKeys = [
+//              bstr,   ; storageKey, a 128-bit AES key
+//              bstr,   ; credentialPrivKey, the private key for credentialKey
+//              bstr    ; proofOfProvisioning SHA-256
+//         ]
+//
+// where storageKey is 16 bytes, credentialPrivateKey is 32 bytes, and proofOfProvisioning
+// SHA-256 is 32 bytes.
+#define EIC_CREDENTIAL_KEYS_CBOR_SIZE_FEATURE_VERSION_202009 52
+#define EIC_CREDENTIAL_KEYS_CBOR_SIZE_FEATURE_VERSION_202101 86
+
+#endif  // ANDROID_HARDWARE_IDENTITY_EIC_COMMON_H
diff --git a/identity/aidl/default/libeic/EicOps.h b/identity/aidl/default/libeic/EicOps.h
index d4fcf0e..df96c7d 100644
--- a/identity/aidl/default/libeic/EicOps.h
+++ b/identity/aidl/default/libeic/EicOps.h
@@ -141,6 +141,10 @@
 // String length, see strlen(3).
 size_t eicStrLen(const char* s);
 
+// Locate a substring, see memmem(3)
+void* eicMemMem(const uint8_t* haystack, size_t haystackLen, const uint8_t* needle,
+                size_t needleLen);
+
 // Memory compare, see CRYPTO_memcmp(3SSL)
 //
 // It takes an amount of time dependent on len, but independent of the contents of the
@@ -151,6 +155,12 @@
 // Random number generation.
 bool eicOpsRandom(uint8_t* buf, size_t numBytes);
 
+// Creates a new non-zero identifier in |id|.
+//
+// Is guaranteed to be non-zero and different than what is already in |id|.
+//
+bool eicNextId(uint32_t* id);
+
 // If |testCredential| is true, returns the 128-bit AES Hardware-Bound Key (16 bytes).
 //
 // Otherwise returns all zeroes (16 bytes).
@@ -186,13 +196,19 @@
 
 // Generates CredentialKey plus an attestation certificate.
 //
-// The attestation certificate will be signed by the attestation keys the secure
-// area has been provisioned with. The given |challenge| and |applicationId|
-// will be used as will |testCredential|.
+// If |attestationKeyBlob| is non-NULL, the certificate must be signed by the
+// the provided attestation key. Else, the certificate must be signed by the
+// attestation key that the secure area has been factory provisioned with. The
+// given |challenge|, |applicationId|, and |testCredential| must be signed
+// into the attestation.
 //
-// The generated certificate will be in X.509 format and returned in |cert|
-// and |certSize| must be set to the size of this array and this function will
-// set it to the size of the certification chain on successfully return.
+// When |attestationKeyBlob| is non-NULL, then |attestationKeyCert| must
+// also be passed so that the underlying implementation can properly chain up
+// the newly-generated certificate to the existing chain.
+//
+// The generated certificate must be in X.509 format and returned in |cert|
+// and |certSize| must be set to the size of this array. This function must
+// set |certSize| to the size of the certification chain on successfully return.
 //
 // This may return either a single certificate or an entire certificate
 // chain. If it returns only a single certificate, the implementation of
@@ -201,8 +217,10 @@
 //
 bool eicOpsCreateCredentialKey(uint8_t privateKey[EIC_P256_PRIV_KEY_SIZE], const uint8_t* challenge,
                                size_t challengeSize, const uint8_t* applicationId,
-                               size_t applicationIdSize, bool testCredential, uint8_t* cert,
-                               size_t* certSize);  // inout
+                               size_t applicationIdSize, bool testCredential,
+                               const uint8_t* attestationKeyBlob, size_t attestationKeyBlobSize,
+                               const uint8_t* attestationKeyCert, size_t attestationKeyCertSize,
+                               uint8_t* /*out*/ cert, size_t* /*inout*/ certSize);
 
 // Generate an X.509 certificate for the key identified by |publicKey| which
 // must be of the form returned by eicOpsCreateEcKey().
@@ -295,6 +313,8 @@
                              int verificationTokenSecurityLevel,
                              const uint8_t* verificationTokenMac, size_t verificationTokenMacSize);
 
+// Also see eicOpsLookupActiveSessionFromId() defined in EicSession.h
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/identity/aidl/default/libeic/EicPresentation.c b/identity/aidl/default/libeic/EicPresentation.c
index 3d13766..104a559 100644
--- a/identity/aidl/default/libeic/EicPresentation.c
+++ b/identity/aidl/default/libeic/EicPresentation.c
@@ -15,22 +15,29 @@
  */
 
 #include "EicPresentation.h"
+#include "EicCommon.h"
+#include "EicSession.h"
 
 #include <inttypes.h>
 
-bool eicPresentationInit(EicPresentation* ctx, bool testCredential, const char* docType,
+// Global used for assigning ids for presentation objects.
+//
+static uint32_t gPresentationLastIdAssigned = 0;
+
+bool eicPresentationInit(EicPresentation* ctx, uint32_t sessionId, bool testCredential,
+                         const char* docType, size_t docTypeLength,
                          const uint8_t* encryptedCredentialKeys,
                          size_t encryptedCredentialKeysSize) {
-    uint8_t credentialKeys[86];
+    uint8_t credentialKeys[EIC_CREDENTIAL_KEYS_CBOR_SIZE_FEATURE_VERSION_202101];
     bool expectPopSha256 = false;
 
     // For feature version 202009 it's 52 bytes long and for feature version 202101 it's 86
     // bytes (the additional data is the ProofOfProvisioning SHA-256). We need
     // to support loading all feature versions.
     //
-    if (encryptedCredentialKeysSize == 52 + 28) {
+    if (encryptedCredentialKeysSize == EIC_CREDENTIAL_KEYS_CBOR_SIZE_FEATURE_VERSION_202009 + 28) {
         /* do nothing */
-    } else if (encryptedCredentialKeysSize == 86 + 28) {
+    } else if (encryptedCredentialKeysSize == EIC_CREDENTIAL_KEYS_CBOR_SIZE_FEATURE_VERSION_202101 + 28) {
         expectPopSha256 = true;
     } else {
         eicDebug("Unexpected size %zd for encryptedCredentialKeys", encryptedCredentialKeysSize);
@@ -38,11 +45,18 @@
     }
 
     eicMemSet(ctx, '\0', sizeof(EicPresentation));
+    ctx->sessionId = sessionId;
+
+    if (!eicNextId(&gPresentationLastIdAssigned)) {
+        eicDebug("Error getting id for object");
+        return false;
+    }
+    ctx->id = gPresentationLastIdAssigned;
 
     if (!eicOpsDecryptAes128Gcm(eicOpsGetHardwareBoundKey(testCredential), encryptedCredentialKeys,
                                 encryptedCredentialKeysSize,
                                 // DocType is the additionalAuthenticatedData
-                                (const uint8_t*)docType, eicStrLen(docType), credentialKeys)) {
+                                (const uint8_t*)docType, docTypeLength, credentialKeys)) {
         eicDebug("Error decrypting CredentialKeys");
         return false;
     }
@@ -85,10 +99,28 @@
     if (expectPopSha256) {
         eicMemCpy(ctx->proofOfProvisioningSha256, credentialKeys + 54, EIC_SHA256_DIGEST_SIZE);
     }
+
+    eicDebug("Initialized presentation with id %" PRIu32, ctx->id);
     return true;
 }
 
-bool eicPresentationGenerateSigningKeyPair(EicPresentation* ctx, const char* docType, time_t now,
+bool eicPresentationShutdown(EicPresentation* ctx) {
+    if (ctx->id == 0) {
+        eicDebug("Trying to shut down presentation with id 0");
+        return false;
+    }
+    eicDebug("Shut down presentation with id %" PRIu32, ctx->id);
+    eicMemSet(ctx, '\0', sizeof(EicPresentation));
+    return true;
+}
+
+bool eicPresentationGetId(EicPresentation* ctx, uint32_t* outId) {
+    *outId = ctx->id;
+    return true;
+}
+
+bool eicPresentationGenerateSigningKeyPair(EicPresentation* ctx, const char* docType,
+                                           size_t docTypeLength, time_t now,
                                            uint8_t* publicKeyCert, size_t* publicKeyCertSize,
                                            uint8_t signingKeyBlob[60]) {
     uint8_t signingKeyPriv[EIC_P256_PRIV_KEY_SIZE];
@@ -114,7 +146,7 @@
     EicCbor cbor;
     eicCborInit(&cbor, cborBuf, sizeof cborBuf);
     eicCborAppendArray(&cbor, 2);
-    eicCborAppendString(&cbor, "ProofOfBinding");
+    eicCborAppendStringZ(&cbor, "ProofOfBinding");
     eicCborAppendByteString(&cbor, ctx->proofOfProvisioningSha256, EIC_SHA256_DIGEST_SIZE);
     if (cbor.size > sizeof(cborBuf)) {
         eicDebug("Exceeded buffer size");
@@ -147,7 +179,7 @@
     }
     if (!eicOpsEncryptAes128Gcm(ctx->storageKey, nonce, signingKeyPriv, sizeof(signingKeyPriv),
                                 // DocType is the additionalAuthenticatedData
-                                (const uint8_t*)docType, eicStrLen(docType), signingKeyBlob)) {
+                                (const uint8_t*)docType, docTypeLength, signingKeyBlob)) {
         eicDebug("Error encrypting signing key");
         return false;
     }
@@ -172,7 +204,7 @@
             eicDebug("Failed generating random challenge");
             return false;
         }
-    } while (ctx->authChallenge == 0);
+    } while (ctx->authChallenge == EIC_KM_AUTH_CHALLENGE_UNSET);
     eicDebug("Created auth challenge %" PRIu64, ctx->authChallenge);
     *authChallenge = ctx->authChallenge;
     return true;
@@ -188,6 +220,24 @@
                                            int coseSignAlg,
                                            const uint8_t* readerSignatureOfToBeSigned,
                                            size_t readerSignatureOfToBeSignedSize) {
+    if (ctx->sessionId != 0) {
+        EicSession* session = eicSessionGetForId(ctx->sessionId);
+        if (session == NULL) {
+            eicDebug("Error looking up session for sessionId %" PRIu32, ctx->sessionId);
+            return false;
+        }
+        EicSha256Ctx sha256;
+        uint8_t sessionTranscriptSha256[EIC_SHA256_DIGEST_SIZE];
+        eicOpsSha256Init(&sha256);
+        eicOpsSha256Update(&sha256, sessionTranscript, sessionTranscriptSize);
+        eicOpsSha256Final(&sha256, sessionTranscriptSha256);
+        if (eicCryptoMemCmp(sessionTranscriptSha256, session->sessionTranscriptSha256,
+                            EIC_SHA256_DIGEST_SIZE) != 0) {
+            eicDebug("SessionTranscript mismatch");
+            return false;
+        }
+    }
+
     if (ctx->readerPublicKeySize == 0) {
         eicDebug("No public key for reader");
         return false;
@@ -219,7 +269,7 @@
     EicCbor cbor;
     eicCborInit(&cbor, NULL, 0);
     eicCborAppendArray(&cbor, 4);
-    eicCborAppendString(&cbor, "Signature1");
+    eicCborAppendStringZ(&cbor, "Signature1");
 
     // The COSE Encoded protected headers is just a single field with
     // COSE_LABEL_ALG (1) -> coseSignAlg (e.g. -7). For simplicitly we just
@@ -277,7 +327,7 @@
     //
     size_t payloadOffset = cbor.size;
     eicCborBegin(&cbor, EIC_CBOR_MAJOR_TYPE_ARRAY, 3);
-    eicCborAppendString(&cbor, "ReaderAuthentication");
+    eicCborAppendStringZ(&cbor, "ReaderAuthentication");
     eicCborAppend(&cbor, sessionTranscript, sessionTranscriptSize);
     eicCborAppendSemantic(&cbor, EIC_CBOR_SEMANTIC_TAG_ENCODED_CBOR);
     eicCborBegin(&cbor, EIC_CBOR_MAJOR_TYPE_BYTE_STRING, requestMessageSize);
@@ -328,6 +378,20 @@
     return true;
 }
 
+static bool getChallenge(EicPresentation* ctx, uint64_t* outAuthChallenge) {
+    // Use authChallenge from session if applicable.
+    *outAuthChallenge = ctx->authChallenge;
+    if (ctx->sessionId != 0) {
+        EicSession* session = eicSessionGetForId(ctx->sessionId);
+        if (session == NULL) {
+            eicDebug("Error looking up session for sessionId %" PRIu32, ctx->sessionId);
+            return false;
+        }
+        *outAuthChallenge = session->authChallenge;
+    }
+    return true;
+}
+
 bool eicPresentationSetAuthToken(EicPresentation* ctx, uint64_t challenge, uint64_t secureUserId,
                                  uint64_t authenticatorId, int hardwareAuthenticatorType,
                                  uint64_t timeStamp, const uint8_t* mac, size_t macSize,
@@ -336,14 +400,19 @@
                                  int verificationTokenSecurityLevel,
                                  const uint8_t* verificationTokenMac,
                                  size_t verificationTokenMacSize) {
+    uint64_t authChallenge;
+    if (!getChallenge(ctx, &authChallenge)) {
+        return false;
+    }
+
     // It doesn't make sense to accept any tokens if eicPresentationCreateAuthChallenge()
     // was never called.
-    if (ctx->authChallenge == 0) {
-        eicDebug("Trying validate tokens when no auth-challenge was previously generated");
+    if (authChallenge == EIC_KM_AUTH_CHALLENGE_UNSET) {
+        eicDebug("Trying to validate tokens when no auth-challenge was previously generated");
         return false;
     }
     // At least the verification-token must have the same challenge as what was generated.
-    if (verificationTokenChallenge != ctx->authChallenge) {
+    if (verificationTokenChallenge != authChallenge) {
         eicDebug("Challenge in verification token does not match the challenge "
                  "previously generated");
         return false;
@@ -352,6 +421,7 @@
                 challenge, secureUserId, authenticatorId, hardwareAuthenticatorType, timeStamp, mac,
                 macSize, verificationTokenChallenge, verificationTokenTimestamp,
                 verificationTokenSecurityLevel, verificationTokenMac, verificationTokenMacSize)) {
+        eicDebug("Error validating authToken");
         return false;
     }
     ctx->authTokenChallenge = challenge;
@@ -375,11 +445,16 @@
     // Only ACP with auth-on-every-presentation - those with timeout == 0 - need the
     // challenge to match...
     if (timeoutMillis == 0) {
-        if (ctx->authTokenChallenge != ctx->authChallenge) {
+        uint64_t authChallenge;
+        if (!getChallenge(ctx, &authChallenge)) {
+            return false;
+        }
+
+        if (ctx->authTokenChallenge != authChallenge) {
             eicDebug("Challenge in authToken (%" PRIu64
                      ") doesn't match the challenge "
                      "that was created (%" PRIu64 ") for this session",
-                     ctx->authTokenChallenge, ctx->authChallenge);
+                     ctx->authTokenChallenge, authChallenge);
             return false;
         }
     }
@@ -438,18 +513,18 @@
                                                  size_t readerCertificateSize,
                                                  bool userAuthenticationRequired, int timeoutMillis,
                                                  uint64_t secureUserId, const uint8_t mac[28],
-                                                 bool* accessGranted) {
+                                                 bool* accessGranted,
+                                                 uint8_t* scratchSpace,
+                                                 size_t scratchSpaceSize) {
     *accessGranted = false;
-
     if (id < 0 || id >= 32) {
         eicDebug("id value of %d is out of allowed range [0, 32[", id);
         return false;
     }
 
     // Validate the MAC
-    uint8_t cborBuffer[EIC_MAX_CBOR_SIZE_FOR_ACCESS_CONTROL_PROFILE];
     EicCbor cborBuilder;
-    eicCborInit(&cborBuilder, cborBuffer, EIC_MAX_CBOR_SIZE_FOR_ACCESS_CONTROL_PROFILE);
+    eicCborInit(&cborBuilder, scratchSpace, scratchSpaceSize);
     if (!eicCborCalcAccessControl(&cborBuilder, id, readerCertificate, readerCertificateSize,
                                   userAuthenticationRequired, timeoutMillis, secureUserId)) {
         return false;
@@ -464,15 +539,15 @@
             checkUserAuth(ctx, userAuthenticationRequired, timeoutMillis, secureUserId);
     bool passedReaderAuth = checkReaderAuth(ctx, readerCertificate, readerCertificateSize);
 
-    ctx->accessControlProfileMaskValidated |= (1 << id);
+    ctx->accessControlProfileMaskValidated |= (1U << id);
     if (readerCertificateSize > 0) {
-        ctx->accessControlProfileMaskUsesReaderAuth |= (1 << id);
+        ctx->accessControlProfileMaskUsesReaderAuth |= (1U << id);
     }
     if (!passedReaderAuth) {
-        ctx->accessControlProfileMaskFailedReaderAuth |= (1 << id);
+        ctx->accessControlProfileMaskFailedReaderAuth |= (1U << id);
     }
     if (!passedUserAuth) {
-        ctx->accessControlProfileMaskFailedUserAuth |= (1 << id);
+        ctx->accessControlProfileMaskFailedUserAuth |= (1U << id);
     }
 
     if (passedUserAuth && passedReaderAuth) {
@@ -486,11 +561,30 @@
                                size_t sessionTranscriptSize,
                                const uint8_t readerEphemeralPublicKey[EIC_P256_PUB_KEY_SIZE],
                                const uint8_t signingKeyBlob[60], const char* docType,
-                               unsigned int numNamespacesWithValues,
+                               size_t docTypeLength, unsigned int numNamespacesWithValues,
                                size_t expectedDeviceNamespacesSize) {
+    if (ctx->sessionId != 0) {
+        EicSession* session = eicSessionGetForId(ctx->sessionId);
+        if (session == NULL) {
+            eicDebug("Error looking up session for sessionId %" PRIu32, ctx->sessionId);
+            return false;
+        }
+        EicSha256Ctx sha256;
+        uint8_t sessionTranscriptSha256[EIC_SHA256_DIGEST_SIZE];
+        eicOpsSha256Init(&sha256);
+        eicOpsSha256Update(&sha256, sessionTranscript, sessionTranscriptSize);
+        eicOpsSha256Final(&sha256, sessionTranscriptSha256);
+        if (eicCryptoMemCmp(sessionTranscriptSha256, session->sessionTranscriptSha256,
+                            EIC_SHA256_DIGEST_SIZE) != 0) {
+            eicDebug("SessionTranscript mismatch");
+            return false;
+        }
+        readerEphemeralPublicKey = session->readerEphemeralPublicKey;
+    }
+
     uint8_t signingKeyPriv[EIC_P256_PRIV_KEY_SIZE];
     if (!eicOpsDecryptAes128Gcm(ctx->storageKey, signingKeyBlob, 60, (const uint8_t*)docType,
-                                eicStrLen(docType), signingKeyPriv)) {
+                                docTypeLength, signingKeyPriv)) {
         eicDebug("Error decrypting signingKeyBlob");
         return false;
     }
@@ -530,7 +624,7 @@
     // ]
     //
     eicCborAppendArray(&ctx->cbor, 4);
-    eicCborAppendString(&ctx->cbor, "MAC0");
+    eicCborAppendStringZ(&ctx->cbor, "MAC0");
 
     // The COSE Encoded protected headers is just a single field with
     // COSE_LABEL_ALG (1) -> COSE_ALG_HMAC_256_256 (5). For simplicitly we just
@@ -566,8 +660,7 @@
     calculatedSize += 1;  // "DeviceAuthentication" less than 24 bytes
     calculatedSize += sizeof("DeviceAuthentication") - 1;  // Don't include trailing NUL
     calculatedSize += sessionTranscriptSize;               // Already CBOR encoded
-    size_t docTypeLen = eicStrLen(docType);
-    calculatedSize += 1 + eicCborAdditionalLengthBytesFor(docTypeLen) + docTypeLen;
+    calculatedSize += 1 + eicCborAdditionalLengthBytesFor(docTypeLength) + docTypeLength;
     calculatedSize += 2;  // Semantic tag EIC_CBOR_SEMANTIC_TAG_ENCODED_CBOR (24)
     calculatedSize += 1 + eicCborAdditionalLengthBytesFor(expectedDeviceNamespacesSize);
     calculatedSize += expectedDeviceNamespacesSize;
@@ -589,9 +682,9 @@
     eicCborBegin(&ctx->cbor, EIC_CBOR_MAJOR_TYPE_BYTE_STRING, calculatedSize);
 
     eicCborAppendArray(&ctx->cbor, 4);
-    eicCborAppendString(&ctx->cbor, "DeviceAuthentication");
+    eicCborAppendStringZ(&ctx->cbor, "DeviceAuthentication");
     eicCborAppend(&ctx->cbor, sessionTranscript, sessionTranscriptSize);
-    eicCborAppendString(&ctx->cbor, docType);
+    eicCborAppendString(&ctx->cbor, docType, docTypeLength);
 
     // For the payload, the _encoded_ form follows here. We handle this by simply
     // opening a bstr, and then writing the CBOR. This requires us to know the
@@ -618,16 +711,18 @@
 }
 
 EicAccessCheckResult eicPresentationStartRetrieveEntryValue(
-        EicPresentation* ctx, const char* nameSpace, const char* name,
-        unsigned int newNamespaceNumEntries, int32_t /* entrySize */,
-        const int* accessControlProfileIds, size_t numAccessControlProfileIds,
+        EicPresentation* ctx, const char* nameSpace, size_t nameSpaceLength,
+        const char* name, size_t nameLength,
+        unsigned int newNamespaceNumEntries, int32_t entrySize,
+        const uint8_t* accessControlProfileIds, size_t numAccessControlProfileIds,
         uint8_t* scratchSpace, size_t scratchSpaceSize) {
+    (void)entrySize;
     uint8_t* additionalDataCbor = scratchSpace;
-    const size_t additionalDataCborBufSize = scratchSpaceSize;
+    size_t additionalDataCborBufferSize = scratchSpaceSize;
     size_t additionalDataCborSize;
 
     if (newNamespaceNumEntries > 0) {
-        eicCborAppendString(&ctx->cbor, nameSpace);
+        eicCborAppendString(&ctx->cbor, nameSpace, nameSpaceLength);
         eicCborAppendMap(&ctx->cbor, newNamespaceNumEntries);
     }
 
@@ -636,8 +731,9 @@
     //
     ctx->accessCheckOk = false;
     if (!eicCborCalcEntryAdditionalData(accessControlProfileIds, numAccessControlProfileIds,
-                                        nameSpace, name, additionalDataCbor,
-                                        additionalDataCborBufSize, &additionalDataCborSize,
+                                        nameSpace, nameSpaceLength, name, nameLength,
+                                        additionalDataCbor, additionalDataCborBufferSize,
+                                        &additionalDataCborSize,
                                         ctx->additionalDataSha256)) {
         return EIC_ACCESS_CHECK_RESULT_FAILED;
     }
@@ -681,7 +777,7 @@
     eicDebug("Result %d for name %s", result, name);
 
     if (result == EIC_ACCESS_CHECK_RESULT_OK) {
-        eicCborAppendString(&ctx->cbor, name);
+        eicCborAppendString(&ctx->cbor, name, nameLength);
         ctx->accessCheckOk = true;
     }
     return result;
@@ -690,18 +786,21 @@
 // Note: |content| must be big enough to hold |encryptedContentSize| - 28 bytes.
 bool eicPresentationRetrieveEntryValue(EicPresentation* ctx, const uint8_t* encryptedContent,
                                        size_t encryptedContentSize, uint8_t* content,
-                                       const char* nameSpace, const char* name,
-                                       const int* accessControlProfileIds,
-                                       size_t numAccessControlProfileIds, uint8_t* scratchSpace,
+                                       const char* nameSpace, size_t nameSpaceLength,
+                                       const char* name, size_t nameLength,
+                                       const uint8_t* accessControlProfileIds,
+                                       size_t numAccessControlProfileIds,
+                                       uint8_t* scratchSpace,
                                        size_t scratchSpaceSize) {
     uint8_t* additionalDataCbor = scratchSpace;
-    const size_t additionalDataCborBufSize = scratchSpaceSize;
+    size_t additionalDataCborBufferSize = scratchSpaceSize;
     size_t additionalDataCborSize;
 
     uint8_t calculatedSha256[EIC_SHA256_DIGEST_SIZE];
     if (!eicCborCalcEntryAdditionalData(accessControlProfileIds, numAccessControlProfileIds,
-                                        nameSpace, name, additionalDataCbor,
-                                        additionalDataCborBufSize, &additionalDataCborSize,
+                                        nameSpace, nameSpaceLength, name, nameLength,
+                                        additionalDataCbor, additionalDataCborBufferSize,
+                                        &additionalDataCborSize,
                                         calculatedSha256)) {
         return false;
     }
@@ -746,9 +845,10 @@
     return true;
 }
 
-bool eicPresentationDeleteCredential(EicPresentation* ctx, const char* docType,
+bool eicPresentationDeleteCredential(EicPresentation* ctx, const char* docType, size_t docTypeLength,
                                      const uint8_t* challenge, size_t challengeSize,
-                                     bool includeChallenge, size_t proofOfDeletionCborSize,
+                                     bool includeChallenge,
+                                     size_t proofOfDeletionCborSize,
                                      uint8_t signatureOfToBeSigned[EIC_ECDSA_P256_SIGNATURE_SIZE]) {
     EicCbor cbor;
 
@@ -766,7 +866,7 @@
     //  ]
     //
     eicCborAppendArray(&cbor, 4);
-    eicCborAppendString(&cbor, "Signature1");
+    eicCborAppendStringZ(&cbor, "Signature1");
 
     // The COSE Encoded protected headers is just a single field with
     // COSE_LABEL_ALG (1) -> COSE_ALG_ECSDA_256 (-7). For simplicitly we just
@@ -787,8 +887,8 @@
 
     // Finally, the CBOR that we're actually signing.
     eicCborAppendArray(&cbor, includeChallenge ? 4 : 3);
-    eicCborAppendString(&cbor, "ProofOfDeletion");
-    eicCborAppendString(&cbor, docType);
+    eicCborAppendStringZ(&cbor, "ProofOfDeletion");
+    eicCborAppendString(&cbor, docType, docTypeLength);
     if (includeChallenge) {
         eicCborAppendByteString(&cbor, challenge, challengeSize);
     }
@@ -804,7 +904,8 @@
     return true;
 }
 
-bool eicPresentationProveOwnership(EicPresentation* ctx, const char* docType, bool testCredential,
+bool eicPresentationProveOwnership(EicPresentation* ctx, const char* docType,
+                                   size_t docTypeLength, bool testCredential,
                                    const uint8_t* challenge, size_t challengeSize,
                                    size_t proofOfOwnershipCborSize,
                                    uint8_t signatureOfToBeSigned[EIC_ECDSA_P256_SIGNATURE_SIZE]) {
@@ -824,7 +925,7 @@
     //  ]
     //
     eicCborAppendArray(&cbor, 4);
-    eicCborAppendString(&cbor, "Signature1");
+    eicCborAppendStringZ(&cbor, "Signature1");
 
     // The COSE Encoded protected headers is just a single field with
     // COSE_LABEL_ALG (1) -> COSE_ALG_ECSDA_256 (-7). For simplicitly we just
@@ -845,8 +946,8 @@
 
     // Finally, the CBOR that we're actually signing.
     eicCborAppendArray(&cbor, 4);
-    eicCborAppendString(&cbor, "ProofOfOwnership");
-    eicCborAppendString(&cbor, docType);
+    eicCborAppendStringZ(&cbor, "ProofOfOwnership");
+    eicCborAppendString(&cbor, docType, docTypeLength);
     eicCborAppendByteString(&cbor, challenge, challengeSize);
     eicCborAppendBool(&cbor, testCredential);
 
diff --git a/identity/aidl/default/libeic/EicPresentation.h b/identity/aidl/default/libeic/EicPresentation.h
index c888049..a031890 100644
--- a/identity/aidl/default/libeic/EicPresentation.h
+++ b/identity/aidl/default/libeic/EicPresentation.h
@@ -30,7 +30,13 @@
 // The maximum size we support for public keys in reader certificates.
 #define EIC_PRESENTATION_MAX_READER_PUBLIC_KEY_SIZE 65
 
+// Constant used to convey that no session is associated with a presentation.
+#define EIC_PRESENTATION_ID_UNSET 0
+
 typedef struct {
+    // A non-zero number unique for this EicPresentation instance
+    uint32_t id;
+
     int featureLevel;
 
     uint8_t storageKey[EIC_AES_128_KEY_SIZE];
@@ -38,6 +44,10 @@
 
     uint8_t ephemeralPrivateKey[EIC_P256_PRIV_KEY_SIZE];
 
+    // If non-zero (not EIC_PRESENTATION_ID_UNSET), the id of the EicSession object this
+    // presentation object is associated with.
+    uint32_t sessionId;
+
     // The challenge generated with eicPresentationCreateAuthChallenge()
     uint64_t authChallenge;
 
@@ -93,11 +103,20 @@
     EicCbor cbor;
 } EicPresentation;
 
-bool eicPresentationInit(EicPresentation* ctx, bool testCredential, const char* docType,
+// If sessionId is zero (EIC_PRESENTATION_ID_UNSET), the presentation object is not associated
+// with a session object. Otherwise it's the id of the session object.
+//
+bool eicPresentationInit(EicPresentation* ctx, uint32_t sessionId, bool testCredential,
+                         const char* docType, size_t docTypeLength,
                          const uint8_t* encryptedCredentialKeys,
                          size_t encryptedCredentialKeysSize);
 
-bool eicPresentationGenerateSigningKeyPair(EicPresentation* ctx, const char* docType, time_t now,
+bool eicPresentationShutdown(EicPresentation* ctx);
+
+bool eicPresentationGetId(EicPresentation* ctx, uint32_t* outId);
+
+bool eicPresentationGenerateSigningKeyPair(EicPresentation* ctx, const char* docType,
+                                           size_t docTypeLength, time_t now,
                                            uint8_t* publicKeyCert, size_t* publicKeyCertSize,
                                            uint8_t signingKeyBlob[60]);
 
@@ -148,12 +167,17 @@
 // be called after pushing that certificate using
 // eicPresentationPushReaderCert().
 //
+// The scratchSpace should be set to a buffer at least 512 bytes. It's done
+// this way to avoid allocating stack space.
+//
 bool eicPresentationValidateAccessControlProfile(EicPresentation* ctx, int id,
                                                  const uint8_t* readerCertificate,
                                                  size_t readerCertificateSize,
                                                  bool userAuthenticationRequired, int timeoutMillis,
                                                  uint64_t secureUserId, const uint8_t mac[28],
-                                                 bool* accessGranted);
+                                                 bool* accessGranted,
+                                                 uint8_t* scratchSpace,
+                                                 size_t scratchSpaceSize);
 
 // Validates that the given requestMessage is signed by the public key in the
 // certificate last set with eicPresentationPushReaderCert().
@@ -196,7 +220,7 @@
                                size_t sessionTranscriptSize,
                                const uint8_t readerEphemeralPublicKey[EIC_P256_PUB_KEY_SIZE],
                                const uint8_t signingKeyBlob[60], const char* docType,
-                               unsigned int numNamespacesWithValues,
+                               size_t docTypeLength, unsigned int numNamespacesWithValues,
                                size_t expectedDeviceNamespacesSize);
 
 // The scratchSpace should be set to a buffer at least 512 bytes (ideally 1024
@@ -204,9 +228,11 @@
 // space.
 //
 EicAccessCheckResult eicPresentationStartRetrieveEntryValue(
-        EicPresentation* ctx, const char* nameSpace, const char* name,
-        unsigned int newNamespaceNumEntries, int32_t entrySize, const int* accessControlProfileIds,
-        size_t numAccessControlProfileIds, uint8_t* scratchSpace, size_t scratchSpaceSize);
+        EicPresentation* ctx, const char* nameSpace, size_t nameSpaceLength,
+        const char* name, size_t nameLength,
+        unsigned int newNamespaceNumEntries, int32_t entrySize,
+        const uint8_t* accessControlProfileIds, size_t numAccessControlProfileIds,
+        uint8_t* scratchSpace, size_t scratchSpaceSize);
 
 // Note: |content| must be big enough to hold |encryptedContentSize| - 28 bytes.
 //
@@ -215,9 +241,11 @@
 //
 bool eicPresentationRetrieveEntryValue(EicPresentation* ctx, const uint8_t* encryptedContent,
                                        size_t encryptedContentSize, uint8_t* content,
-                                       const char* nameSpace, const char* name,
-                                       const int* accessControlProfileIds,
-                                       size_t numAccessControlProfileIds, uint8_t* scratchSpace,
+                                       const char* nameSpace, size_t nameSpaceLength,
+                                       const char* name, size_t nameLength,
+                                       const uint8_t* accessControlProfileIds,
+                                       size_t numAccessControlProfileIds,
+                                       uint8_t* scratchSpace,
                                        size_t scratchSpaceSize);
 
 // Returns the HMAC-SHA256 of |ToBeMaced| as per RFC 8051 "6.3. How to Compute
@@ -229,7 +257,7 @@
 // the ToBeSigned CBOR from RFC 8051 "4.4. Signing and Verification Process"
 // where content is set to the ProofOfDeletion CBOR.
 //
-bool eicPresentationDeleteCredential(EicPresentation* ctx, const char* docType,
+bool eicPresentationDeleteCredential(EicPresentation* ctx, const char* docType, size_t docTypeLength,
                                      const uint8_t* challenge, size_t challengeSize,
                                      bool includeChallenge, size_t proofOfDeletionCborSize,
                                      uint8_t signatureOfToBeSigned[EIC_ECDSA_P256_SIGNATURE_SIZE]);
@@ -238,8 +266,8 @@
 // the ToBeSigned CBOR from RFC 8051 "4.4. Signing and Verification Process"
 // where content is set to the ProofOfOwnership CBOR.
 //
-bool eicPresentationProveOwnership(EicPresentation* ctx, const char* docType, bool testCredential,
-                                   const uint8_t* challenge, size_t challengeSize,
+bool eicPresentationProveOwnership(EicPresentation* ctx, const char* docType, size_t docTypeLength,
+                                   bool testCredential, const uint8_t* challenge, size_t challengeSize,
                                    size_t proofOfOwnershipCborSize,
                                    uint8_t signatureOfToBeSigned[EIC_ECDSA_P256_SIGNATURE_SIZE]);
 
diff --git a/identity/aidl/default/libeic/EicProvisioning.c b/identity/aidl/default/libeic/EicProvisioning.c
index 3b4148e..ff009dd 100644
--- a/identity/aidl/default/libeic/EicProvisioning.c
+++ b/identity/aidl/default/libeic/EicProvisioning.c
@@ -15,9 +15,23 @@
  */
 
 #include "EicProvisioning.h"
+#include "EicCommon.h"
+
+#include <inttypes.h>
+
+// Global used for assigning ids for provisioning objects.
+//
+static uint32_t gProvisioningLastIdAssigned = 0;
 
 bool eicProvisioningInit(EicProvisioning* ctx, bool testCredential) {
     eicMemSet(ctx, '\0', sizeof(EicProvisioning));
+
+    if (!eicNextId(&gProvisioningLastIdAssigned)) {
+        eicDebug("Error getting id for object");
+        return false;
+    }
+    ctx->id = gProvisioningLastIdAssigned;
+
     ctx->testCredential = testCredential;
     if (!eicOpsRandom(ctx->storageKey, EIC_AES_128_KEY_SIZE)) {
         return false;
@@ -27,18 +41,18 @@
 }
 
 bool eicProvisioningInitForUpdate(EicProvisioning* ctx, bool testCredential, const char* docType,
-                                  const uint8_t* encryptedCredentialKeys,
+                                  size_t docTypeLength, const uint8_t* encryptedCredentialKeys,
                                   size_t encryptedCredentialKeysSize) {
-    uint8_t credentialKeys[86];
+    uint8_t credentialKeys[EIC_CREDENTIAL_KEYS_CBOR_SIZE_FEATURE_VERSION_202101];
 
     // For feature version 202009 it's 52 bytes long and for feature version 202101 it's 86
     // bytes (the additional data is the ProofOfProvisioning SHA-256). We need
     // to support loading all feature versions.
     //
     bool expectPopSha256 = false;
-    if (encryptedCredentialKeysSize == 52 + 28) {
+    if (encryptedCredentialKeysSize == EIC_CREDENTIAL_KEYS_CBOR_SIZE_FEATURE_VERSION_202009 + 28) {
         /* do nothing */
-    } else if (encryptedCredentialKeysSize == 86 + 28) {
+    } else if (encryptedCredentialKeysSize == EIC_CREDENTIAL_KEYS_CBOR_SIZE_FEATURE_VERSION_202101 + 28) {
         expectPopSha256 = true;
     } else {
         eicDebug("Unexpected size %zd for encryptedCredentialKeys", encryptedCredentialKeysSize);
@@ -46,12 +60,19 @@
     }
 
     eicMemSet(ctx, '\0', sizeof(EicProvisioning));
+
+    if (!eicNextId(&gProvisioningLastIdAssigned)) {
+        eicDebug("Error getting id for object");
+        return false;
+    }
+    ctx->id = gProvisioningLastIdAssigned;
+
     ctx->testCredential = testCredential;
 
     if (!eicOpsDecryptAes128Gcm(eicOpsGetHardwareBoundKey(testCredential), encryptedCredentialKeys,
                                 encryptedCredentialKeysSize,
                                 // DocType is the additionalAuthenticatedData
-                                (const uint8_t*)docType, eicStrLen(docType), credentialKeys)) {
+                                (const uint8_t*)docType, docTypeLength, credentialKeys)) {
         eicDebug("Error decrypting CredentialKeys");
         return false;
     }
@@ -95,9 +116,27 @@
     return true;
 }
 
+bool eicProvisioningShutdown(EicProvisioning* ctx) {
+    if (ctx->id == 0) {
+        eicDebug("Trying to shut down provsioning with id 0");
+        return false;
+    }
+    eicDebug("Shut down provsioning with id %" PRIu32, ctx->id);
+    eicMemSet(ctx, '\0', sizeof(EicProvisioning));
+    return true;
+}
+
+bool eicProvisioningGetId(EicProvisioning* ctx, uint32_t* outId) {
+    *outId = ctx->id;
+    return true;
+}
+
 bool eicProvisioningCreateCredentialKey(EicProvisioning* ctx, const uint8_t* challenge,
                                         size_t challengeSize, const uint8_t* applicationId,
-                                        size_t applicationIdSize, uint8_t* publicKeyCert,
+                                        size_t applicationIdSize, const uint8_t* attestationKeyBlob,
+                                        size_t attestationKeyBlobSize,
+                                        const uint8_t* attestationKeyCert,
+                                        size_t attestationKeyCertSize, uint8_t* publicKeyCert,
                                         size_t* publicKeyCertSize) {
     if (ctx->isUpdate) {
         eicDebug("Cannot create CredentialKey on update");
@@ -106,7 +145,9 @@
 
     if (!eicOpsCreateCredentialKey(ctx->credentialPrivateKey, challenge, challengeSize,
                                    applicationId, applicationIdSize, ctx->testCredential,
-                                   publicKeyCert, publicKeyCertSize)) {
+                                   attestationKeyBlob, attestationKeyBlobSize, attestationKeyCert,
+                                   attestationKeyCertSize, publicKeyCert, publicKeyCertSize)) {
+        eicDebug("Error creating credential key");
         return false;
     }
     return true;
@@ -114,7 +155,7 @@
 
 bool eicProvisioningStartPersonalization(EicProvisioning* ctx, int accessControlProfileCount,
                                          const int* entryCounts, size_t numEntryCounts,
-                                         const char* docType,
+                                         const char* docType, size_t docTypeLength,
                                          size_t expectedProofOfProvisioningSize) {
     if (numEntryCounts >= EIC_MAX_NUM_NAMESPACES) {
         return false;
@@ -150,7 +191,7 @@
     //  ]
     //
     eicCborAppendArray(&ctx->cbor, 4);
-    eicCborAppendString(&ctx->cbor, "Signature1");
+    eicCborAppendStringZ(&ctx->cbor, "Signature1");
 
     // The COSE Encoded protected headers is just a single field with
     // COSE_LABEL_ALG (1) -> COSE_ALG_ECSDA_256 (-7). For simplicitly we just
@@ -174,8 +215,8 @@
     eicCborEnableSecondaryDigesterSha256(&ctx->cbor, &ctx->proofOfProvisioningDigester);
 
     eicCborAppendArray(&ctx->cbor, 5);
-    eicCborAppendString(&ctx->cbor, "ProofOfProvisioning");
-    eicCborAppendString(&ctx->cbor, docType);
+    eicCborAppendStringZ(&ctx->cbor, "ProofOfProvisioning");
+    eicCborAppendString(&ctx->cbor, docType, docTypeLength);
 
     eicCborAppendArray(&ctx->cbor, accessControlProfileCount);
 
@@ -185,12 +226,12 @@
 bool eicProvisioningAddAccessControlProfile(EicProvisioning* ctx, int id,
                                             const uint8_t* readerCertificate,
                                             size_t readerCertificateSize,
-                                            bool userAuthenticationRequired, uint64_t timeoutMillis,
-                                            uint64_t secureUserId, uint8_t outMac[28]) {
-    uint8_t cborBuffer[EIC_MAX_CBOR_SIZE_FOR_ACCESS_CONTROL_PROFILE];
+                                            bool userAuthenticationRequired,
+                                            uint64_t timeoutMillis, uint64_t secureUserId,
+                                            uint8_t outMac[28], uint8_t* scratchSpace,
+                                            size_t scratchSpaceSize) {
     EicCbor cborBuilder;
-
-    eicCborInit(&cborBuilder, cborBuffer, EIC_MAX_CBOR_SIZE_FOR_ACCESS_CONTROL_PROFILE);
+    eicCborInit(&cborBuilder, scratchSpace, scratchSpaceSize);
 
     if (!eicCborCalcAccessControl(&cborBuilder, id, readerCertificate, readerCertificateSize,
                                   userAuthenticationRequired, timeoutMillis, secureUserId)) {
@@ -209,7 +250,7 @@
 
     // The ACP CBOR in the provisioning receipt doesn't include secureUserId so build
     // it again.
-    eicCborInit(&cborBuilder, cborBuffer, EIC_MAX_CBOR_SIZE_FOR_ACCESS_CONTROL_PROFILE);
+    eicCborInit(&cborBuilder, scratchSpace, scratchSpaceSize);
     if (!eicCborCalcAccessControl(&cborBuilder, id, readerCertificate, readerCertificateSize,
                                   userAuthenticationRequired, timeoutMillis,
                                   0 /* secureUserId */)) {
@@ -222,9 +263,10 @@
     return true;
 }
 
-bool eicProvisioningBeginAddEntry(EicProvisioning* ctx, const int* accessControlProfileIds,
+bool eicProvisioningBeginAddEntry(EicProvisioning* ctx, const uint8_t* accessControlProfileIds,
                                   size_t numAccessControlProfileIds, const char* nameSpace,
-                                  const char* name, uint64_t entrySize, uint8_t* scratchSpace,
+                                  size_t nameSpaceLength, const char* name, size_t nameLength,
+                                  uint64_t entrySize, uint8_t* scratchSpace,
                                   size_t scratchSpaceSize) {
     uint8_t* additionalDataCbor = scratchSpace;
     const size_t additionalDataCborBufSize = scratchSpaceSize;
@@ -233,9 +275,9 @@
     // We'll need to calc and store a digest of additionalData to check that it's the same
     // additionalData being passed in for every eicProvisioningAddEntryValue() call...
     if (!eicCborCalcEntryAdditionalData(accessControlProfileIds, numAccessControlProfileIds,
-                                        nameSpace, name, additionalDataCbor,
-                                        additionalDataCborBufSize, &additionalDataCborSize,
-                                        ctx->additionalDataSha256)) {
+                                        nameSpace, nameSpaceLength, name, nameLength,
+                                        additionalDataCbor, additionalDataCborBufSize,
+                                        &additionalDataCborSize, ctx->additionalDataSha256)) {
         return false;
     }
 
@@ -244,7 +286,7 @@
         ctx->curNamespaceNumProcessed = 0;
         // Opens the main map: { * Namespace => [ + Entry ] }
         eicCborAppendMap(&ctx->cbor, ctx->numEntryCounts);
-        eicCborAppendString(&ctx->cbor, nameSpace);
+        eicCborAppendString(&ctx->cbor, nameSpace, nameSpaceLength);
         // Opens the per-namespace array: [ + Entry ]
         eicCborAppendArray(&ctx->cbor, ctx->entryCounts[ctx->curNamespace]);
     }
@@ -252,37 +294,39 @@
     if (ctx->curNamespaceNumProcessed == ctx->entryCounts[ctx->curNamespace]) {
         ctx->curNamespace += 1;
         ctx->curNamespaceNumProcessed = 0;
-        eicCborAppendString(&ctx->cbor, nameSpace);
+        eicCborAppendString(&ctx->cbor, nameSpace, nameSpaceLength);
         // Opens the per-namespace array: [ + Entry ]
         eicCborAppendArray(&ctx->cbor, ctx->entryCounts[ctx->curNamespace]);
     }
 
     eicCborAppendMap(&ctx->cbor, 3);
-    eicCborAppendString(&ctx->cbor, "name");
-    eicCborAppendString(&ctx->cbor, name);
+    eicCborAppendStringZ(&ctx->cbor, "name");
+    eicCborAppendString(&ctx->cbor, name, nameLength);
 
     ctx->curEntrySize = entrySize;
     ctx->curEntryNumBytesReceived = 0;
 
-    eicCborAppendString(&ctx->cbor, "value");
+    eicCborAppendStringZ(&ctx->cbor, "value");
 
     ctx->curNamespaceNumProcessed += 1;
     return true;
 }
 
-bool eicProvisioningAddEntryValue(EicProvisioning* ctx, const int* accessControlProfileIds,
+bool eicProvisioningAddEntryValue(EicProvisioning* ctx, const uint8_t* accessControlProfileIds,
                                   size_t numAccessControlProfileIds, const char* nameSpace,
-                                  const char* name, const uint8_t* content, size_t contentSize,
+                                  size_t nameSpaceLength, const char* name, size_t nameLength,
+                                  const uint8_t* content, size_t contentSize,
                                   uint8_t* outEncryptedContent, uint8_t* scratchSpace,
                                   size_t scratchSpaceSize) {
     uint8_t* additionalDataCbor = scratchSpace;
     const size_t additionalDataCborBufSize = scratchSpaceSize;
     size_t additionalDataCborSize;
-
     uint8_t calculatedSha256[EIC_SHA256_DIGEST_SIZE];
+
     if (!eicCborCalcEntryAdditionalData(accessControlProfileIds, numAccessControlProfileIds,
-                                        nameSpace, name, additionalDataCbor,
-                                        additionalDataCborBufSize, &additionalDataCborSize,
+                                        nameSpace, nameSpaceLength, name, nameLength,
+                                        additionalDataCbor, additionalDataCborBufSize,
+                                        &additionalDataCborSize,
                                         calculatedSha256)) {
         return false;
     }
@@ -305,7 +349,7 @@
     // If done with this entry, close the map
     ctx->curEntryNumBytesReceived += contentSize;
     if (ctx->curEntryNumBytesReceived == ctx->curEntrySize) {
-        eicCborAppendString(&ctx->cbor, "accessControlProfiles");
+        eicCborAppendStringZ(&ctx->cbor, "accessControlProfiles");
         eicCborAppendArray(&ctx->cbor, numAccessControlProfileIds);
         for (size_t n = 0; n < numAccessControlProfileIds; n++) {
             eicCborAppendNumber(&ctx->cbor, accessControlProfileIds[n]);
@@ -337,6 +381,7 @@
 }
 
 bool eicProvisioningFinishGetCredentialData(EicProvisioning* ctx, const char* docType,
+                                            size_t docTypeLength,
                                             uint8_t* encryptedCredentialKeys,
                                             size_t* encryptedCredentialKeysSize) {
     EicCbor cbor;
@@ -367,7 +412,7 @@
     if (!eicOpsEncryptAes128Gcm(
                 eicOpsGetHardwareBoundKey(ctx->testCredential), nonce, cborBuf, cbor.size,
                 // DocType is the additionalAuthenticatedData
-                (const uint8_t*)docType, eicStrLen(docType), encryptedCredentialKeys)) {
+                (const uint8_t*)docType, docTypeLength, encryptedCredentialKeys)) {
         eicDebug("Error encrypting CredentialKeys");
         return false;
     }
diff --git a/identity/aidl/default/libeic/EicProvisioning.h b/identity/aidl/default/libeic/EicProvisioning.h
index f064787..2619bfc 100644
--- a/identity/aidl/default/libeic/EicProvisioning.h
+++ b/identity/aidl/default/libeic/EicProvisioning.h
@@ -31,6 +31,9 @@
 #define EIC_MAX_NUM_ACCESS_CONTROL_PROFILE_IDS 32
 
 typedef struct {
+    // A non-zero number unique for this EicProvisioning instance
+    uint32_t id;
+
     // Set by eicCreateCredentialKey() OR eicProvisioningInitForUpdate()
     uint8_t credentialPrivateKey[EIC_P256_PRIV_KEY_SIZE];
 
@@ -65,31 +68,44 @@
 bool eicProvisioningInit(EicProvisioning* ctx, bool testCredential);
 
 bool eicProvisioningInitForUpdate(EicProvisioning* ctx, bool testCredential, const char* docType,
-                                  const uint8_t* encryptedCredentialKeys,
+                                  size_t docTypeLength, const uint8_t* encryptedCredentialKeys,
                                   size_t encryptedCredentialKeysSize);
 
+bool eicProvisioningShutdown(EicProvisioning* ctx);
+
+bool eicProvisioningGetId(EicProvisioning* ctx, uint32_t* outId);
+
 bool eicProvisioningCreateCredentialKey(EicProvisioning* ctx, const uint8_t* challenge,
                                         size_t challengeSize, const uint8_t* applicationId,
-                                        size_t applicationIdSize, uint8_t* publicKeyCert,
+                                        size_t applicationIdSize, const uint8_t* attestationKeyBlob,
+                                        size_t attestationKeyBlobSize,
+                                        const uint8_t* attestationKeyCert,
+                                        size_t attestationKeyCertSize, uint8_t* publicKeyCert,
                                         size_t* publicKeyCertSize);
 
 bool eicProvisioningStartPersonalization(EicProvisioning* ctx, int accessControlProfileCount,
                                          const int* entryCounts, size_t numEntryCounts,
-                                         const char* docType,
+                                         const char* docType, size_t docTypeLength,
                                          size_t expectedProofOfProvisioningingSize);
 
-bool eicProvisioningAddAccessControlProfile(EicProvisioning* ctx, int id,
-                                            const uint8_t* readerCertificate,
-                                            size_t readerCertificateSize,
-                                            bool userAuthenticationRequired, uint64_t timeoutMillis,
-                                            uint64_t secureUserId, uint8_t outMac[28]);
-
 // The scratchSpace should be set to a buffer at least 512 bytes. It's done this way to
 // avoid allocating stack space.
 //
-bool eicProvisioningBeginAddEntry(EicProvisioning* ctx, const int* accessControlProfileIds,
+bool eicProvisioningAddAccessControlProfile(EicProvisioning* ctx, int id,
+                                            const uint8_t* readerCertificate,
+                                            size_t readerCertificateSize,
+                                            bool userAuthenticationRequired,
+                                            uint64_t timeoutMillis, uint64_t secureUserId,
+                                            uint8_t outMac[28], uint8_t* scratchSpace,
+                                            size_t scratchSpaceSize);
+
+// The scratchSpace should be set to a buffer at least 512 bytes. It's done this way to
+// avoid allocating stack space.
+//
+bool eicProvisioningBeginAddEntry(EicProvisioning* ctx, const uint8_t* accessControlProfileIds,
                                   size_t numAccessControlProfileIds, const char* nameSpace,
-                                  const char* name, uint64_t entrySize, uint8_t* scratchSpace,
+                                  size_t nameSpaceLength, const char* name, size_t nameLength,
+                                  uint64_t entrySize, uint8_t* scratchSpace,
                                   size_t scratchSpaceSize);
 
 // The outEncryptedContent array must be contentSize + 28 bytes long.
@@ -97,9 +113,10 @@
 // The scratchSpace should be set to a buffer at least 512 bytes. It's done this way to
 // avoid allocating stack space.
 //
-bool eicProvisioningAddEntryValue(EicProvisioning* ctx, const int* accessControlProfileIds,
+bool eicProvisioningAddEntryValue(EicProvisioning* ctx, const uint8_t* accessControlProfileIds,
                                   size_t numAccessControlProfileIds, const char* nameSpace,
-                                  const char* name, const uint8_t* content, size_t contentSize,
+                                  size_t nameSpaceLength, const char* name, size_t nameLength,
+                                  const uint8_t* content, size_t contentSize,
                                   uint8_t* outEncryptedContent, uint8_t* scratchSpace,
                                   size_t scratchSpaceSize);
 
@@ -128,6 +145,7 @@
 // |encryptedCredentialKeys| will be no longer than 86 + 28 = 114 bytes.
 //
 bool eicProvisioningFinishGetCredentialData(EicProvisioning* ctx, const char* docType,
+                                            size_t docTypeLength,
                                             uint8_t* encryptedCredentialKeys,
                                             size_t* encryptedCredentialKeysSize);
 
diff --git a/identity/aidl/default/libeic/EicSession.c b/identity/aidl/default/libeic/EicSession.c
new file mode 100644
index 0000000..d0c7a0d
--- /dev/null
+++ b/identity/aidl/default/libeic/EicSession.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <inttypes.h>
+
+#include "EicCommon.h"
+#include "EicSession.h"
+
+// Global used for assigning ids for session objects.
+//
+static uint32_t gSessionLastIdAssigned = 0;
+
+// The current session object or NULL if never initialized or if it has been shut down.
+//
+static EicSession* gSessionCurrent = NULL;
+
+EicSession* eicSessionGetForId(uint32_t sessionId) {
+    if (gSessionCurrent != NULL && gSessionCurrent->id == sessionId) {
+        return gSessionCurrent;
+    }
+    return NULL;
+}
+
+bool eicSessionInit(EicSession* ctx) {
+    eicMemSet(ctx, '\0', sizeof(EicSession));
+
+    if (!eicNextId(&gSessionLastIdAssigned)) {
+        eicDebug("Error getting id for object");
+        return false;
+    }
+    ctx->id = gSessionLastIdAssigned;
+
+    do {
+        if (!eicOpsRandom((uint8_t*)&(ctx->authChallenge), sizeof(ctx->authChallenge))) {
+            eicDebug("Failed generating random challenge");
+            return false;
+        }
+    } while (ctx->authChallenge == EIC_KM_AUTH_CHALLENGE_UNSET);
+
+    if (!eicOpsCreateEcKey(ctx->ephemeralPrivateKey, ctx->ephemeralPublicKey)) {
+        eicDebug("Error creating ephemeral key-pair");
+        return false;
+    }
+
+    gSessionCurrent = ctx;
+    eicDebug("Initialized session with id %" PRIu32, ctx->id);
+    return true;
+}
+
+bool eicSessionShutdown(EicSession* ctx) {
+    if (ctx->id == 0) {
+        eicDebug("Trying to shut down session with id 0");
+        return false;
+    }
+    eicDebug("Shut down session with id %" PRIu32, ctx->id);
+    eicMemSet(ctx, '\0', sizeof(EicSession));
+    gSessionCurrent = NULL;
+    return true;
+}
+
+bool eicSessionGetId(EicSession* ctx, uint32_t* outId) {
+    *outId = ctx->id;
+    return true;
+}
+
+bool eicSessionGetAuthChallenge(EicSession* ctx, uint64_t* outAuthChallenge) {
+    *outAuthChallenge = ctx->authChallenge;
+    return true;
+}
+
+bool eicSessionGetEphemeralKeyPair(EicSession* ctx,
+                                   uint8_t ephemeralPrivateKey[EIC_P256_PRIV_KEY_SIZE]) {
+    eicMemCpy(ephemeralPrivateKey, ctx->ephemeralPrivateKey, EIC_P256_PRIV_KEY_SIZE);
+    return true;
+}
+
+bool eicSessionSetReaderEphemeralPublicKey(
+        EicSession* ctx, const uint8_t readerEphemeralPublicKey[EIC_P256_PUB_KEY_SIZE]) {
+    eicMemCpy(ctx->readerEphemeralPublicKey, readerEphemeralPublicKey, EIC_P256_PUB_KEY_SIZE);
+    return true;
+}
+
+bool eicSessionSetSessionTranscript(EicSession* ctx, const uint8_t* sessionTranscript,
+                                    size_t sessionTranscriptSize) {
+    // Only accept the SessionTranscript if X and Y from the ephemeral key
+    // we created is somewhere in SessionTranscript...
+    //
+    if (eicMemMem(sessionTranscript, sessionTranscriptSize, ctx->ephemeralPublicKey,
+                  EIC_P256_PUB_KEY_SIZE / 2) == NULL) {
+        eicDebug("Error finding X from ephemeralPublicKey in sessionTranscript");
+        return false;
+    }
+    if (eicMemMem(sessionTranscript, sessionTranscriptSize,
+                  ctx->ephemeralPublicKey + EIC_P256_PUB_KEY_SIZE / 2,
+                  EIC_P256_PUB_KEY_SIZE / 2) == NULL) {
+        eicDebug("Error finding Y from ephemeralPublicKey in sessionTranscript");
+        return false;
+    }
+
+    // To save space we only store the SHA-256 of SessionTranscript
+    //
+    EicSha256Ctx shaCtx;
+    eicOpsSha256Init(&shaCtx);
+    eicOpsSha256Update(&shaCtx, sessionTranscript, sessionTranscriptSize);
+    eicOpsSha256Final(&shaCtx, ctx->sessionTranscriptSha256);
+    return true;
+}
diff --git a/identity/aidl/default/libeic/EicSession.h b/identity/aidl/default/libeic/EicSession.h
new file mode 100644
index 0000000..0303dae
--- /dev/null
+++ b/identity/aidl/default/libeic/EicSession.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if !defined(EIC_INSIDE_LIBEIC_H) && !defined(EIC_COMPILATION)
+#error "Never include this file directly, include libeic.h instead."
+#endif
+
+#ifndef ANDROID_HARDWARE_IDENTITY_EIC_SESSION_H
+#define ANDROID_HARDWARE_IDENTITY_EIC_SESSION_H
+
+#include "EicOps.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+    // A non-zero number unique for this EicSession instance
+    uint32_t id;
+
+    // The challenge generated at construction time by eicSessionInit().
+    uint64_t authChallenge;
+
+    uint8_t ephemeralPrivateKey[EIC_P256_PRIV_KEY_SIZE];
+    uint8_t ephemeralPublicKey[EIC_P256_PUB_KEY_SIZE];
+
+    uint8_t readerEphemeralPublicKey[EIC_P256_PUB_KEY_SIZE];
+
+    uint8_t sessionTranscriptSha256[EIC_SHA256_DIGEST_SIZE];
+
+} EicSession;
+
+bool eicSessionInit(EicSession* ctx);
+
+bool eicSessionShutdown(EicSession* ctx);
+
+bool eicSessionGetId(EicSession* ctx, uint32_t* outId);
+
+bool eicSessionGetAuthChallenge(EicSession* ctx, uint64_t* outAuthChallenge);
+
+bool eicSessionGetEphemeralKeyPair(EicSession* ctx,
+                                   uint8_t ephemeralPrivateKey[EIC_P256_PRIV_KEY_SIZE]);
+
+bool eicSessionSetReaderEphemeralPublicKey(
+        EicSession* ctx, const uint8_t readerEphemeralPublicKey[EIC_P256_PUB_KEY_SIZE]);
+
+bool eicSessionSetSessionTranscript(EicSession* ctx, const uint8_t* sessionTranscript,
+                                    size_t sessionTranscriptSize);
+
+// Looks up an active session with the given id.
+//
+// Returns NULL if no active session with the given id is found.
+//
+EicSession* eicSessionGetForId(uint32_t sessionId);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // ANDROID_HARDWARE_IDENTITY_EIC_PRESENTATION_H
diff --git a/identity/aidl/default/libeic/libeic.h b/identity/aidl/default/libeic/libeic.h
index 88abef8..d89fc9a 100644
--- a/identity/aidl/default/libeic/libeic.h
+++ b/identity/aidl/default/libeic/libeic.h
@@ -27,9 +27,11 @@
  */
 #define EIC_INSIDE_LIBEIC_H
 #include "EicCbor.h"
+#include "EicCommon.h"
 #include "EicOps.h"
 #include "EicPresentation.h"
 #include "EicProvisioning.h"
+#include "EicSession.h"
 #undef EIC_INSIDE_LIBEIC_H
 
 #ifdef __cplusplus
diff --git a/identity/aidl/default/service.cpp b/identity/aidl/default/service.cpp
index c290c08..ed3c4cb 100644
--- a/identity/aidl/default/service.cpp
+++ b/identity/aidl/default/service.cpp
@@ -16,6 +16,7 @@
 
 #define LOG_TAG "android.hardware.identity-service"
 
+#include <aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.h>
 #include <android-base/logging.h>
 #include <android/binder_manager.h>
 #include <android/binder_process.h>
@@ -26,24 +27,39 @@
 
 using ::android::sp;
 using ::android::base::InitLogging;
+using ::android::base::LogdLogger;
+using ::android::base::LogId;
+using ::android::base::LogSeverity;
 using ::android::base::StderrLogger;
 
 using ::aidl::android::hardware::identity::IdentityCredentialStore;
+using ::aidl::android::hardware::security::keymint::IRemotelyProvisionedComponent;
 using ::android::hardware::identity::FakeSecureHardwareProxyFactory;
 using ::android::hardware::identity::SecureHardwareProxyFactory;
 
+void ComboLogger(LogId id, LogSeverity severity, const char* tag, const char* file,
+                 unsigned int line, const char* message) {
+    StderrLogger(id, severity, tag, file, line, message);
+
+    static LogdLogger logdLogger;
+    logdLogger(id, severity, tag, file, line, message);
+}
+
 int main(int /*argc*/, char* argv[]) {
-    InitLogging(argv, StderrLogger);
+    InitLogging(argv, ComboLogger);
 
     sp<SecureHardwareProxyFactory> hwProxyFactory = new FakeSecureHardwareProxyFactory();
+    const std::string remotelyProvisionedComponentName =
+            std::string(IRemotelyProvisionedComponent::descriptor) + "/default";
 
     ABinderProcess_setThreadPoolMaxThreadCount(0);
     std::shared_ptr<IdentityCredentialStore> store =
-            ndk::SharedRefBase::make<IdentityCredentialStore>(hwProxyFactory);
+            ndk::SharedRefBase::make<IdentityCredentialStore>(hwProxyFactory,
+                                                              remotelyProvisionedComponentName);
 
     const std::string instance = std::string() + IdentityCredentialStore::descriptor + "/default";
     binder_status_t status = AServiceManager_addService(store->asBinder().get(), instance.c_str());
-    CHECK(status == STATUS_OK);
+    CHECK_EQ(status, STATUS_OK);
 
     ABinderProcess_joinThreadPool();
     return EXIT_FAILURE;  // should not reach
diff --git a/identity/aidl/vts/Android.bp b/identity/aidl/vts/Android.bp
index 61d15d2..dc010d6 100644
--- a/identity/aidl/vts/Android.bp
+++ b/identity/aidl/vts/Android.bp
@@ -11,6 +11,8 @@
     name: "VtsHalIdentityTargetTest",
     defaults: [
         "VtsHalTargetTestDefaults",
+        "keymint_use_latest_hal_aidl_cpp_static",
+        "keymint_use_latest_hal_aidl_ndk_static",
         "use_libaidlvintf_gtest_helper_static",
     ],
     cflags: [
@@ -28,26 +30,32 @@
         "EndToEndTests.cpp",
         "TestCredentialTests.cpp",
         "AuthenticationKeyTests.cpp",
+        "PresentationSessionTests.cpp",
     ],
     shared_libs: [
         "libbinder",
+        "libbinder_ndk",
         "libcrypto",
     ],
     static_libs: [
+        "android.hardware.security.secureclock-V1-ndk",
         "libcppbor_external",
         "libcppcose_rkp",
         "libkeymaster_portable",
+        "libkeymint_vts_test_utils",
         "libpuresoftkeymasterdevice",
         "android.hardware.keymaster@4.0",
         "android.hardware.identity-support-lib",
-        "android.hardware.identity-V3-cpp",
-        "android.hardware.keymaster-V3-cpp",
-        "android.hardware.keymaster-V3-ndk_platform",
+        "android.hardware.identity-V4-cpp",
+        "android.hardware.keymaster-V4-cpp",
+        "android.hardware.keymaster-V4-ndk",
         "libkeymaster4support",
         "libkeymaster4_1support",
+        "libkeymint_remote_prov_support",
     ],
     test_suites: [
         "general-tests",
         "vts",
     ],
+    require_root: true,
 }
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/identity/aidl/vts/DeleteCredentialTests.cpp b/identity/aidl/vts/DeleteCredentialTests.cpp
index 7627c9c..a126463 100644
--- a/identity/aidl/vts/DeleteCredentialTests.cpp
+++ b/identity/aidl/vts/DeleteCredentialTests.cpp
@@ -146,7 +146,9 @@
                                 credentialData_, &credential)
                         .isOk());
 
-    vector<uint8_t> challenge = {65, 66, 67};
+    // Implementations must support at least 32 bytes.
+    string challengeString = "0123456789abcdef0123456789abcdef";
+    vector<uint8_t> challenge(challengeString.begin(), challengeString.end());
     vector<uint8_t> proofOfDeletionSignature;
     ASSERT_TRUE(
             credential->deleteCredentialWithChallenge(challenge, &proofOfDeletionSignature).isOk());
@@ -154,8 +156,13 @@
             support::coseSignGetPayload(proofOfDeletionSignature);
     ASSERT_TRUE(proofOfDeletion);
     string cborPretty = cppbor::prettyPrint(proofOfDeletion.value(), 32, {});
-    EXPECT_EQ("['ProofOfDeletion', 'org.iso.18013-5.2019.mdl', {0x41, 0x42, 0x43}, true, ]",
-              cborPretty);
+    EXPECT_EQ(
+            "['ProofOfDeletion', 'org.iso.18013-5.2019.mdl', {"
+            "0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, "
+            "0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, "
+            "0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, "
+            "0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66}, true, ]",
+            cborPretty);
     EXPECT_TRUE(support::coseCheckEcDsaSignature(proofOfDeletionSignature, {},  // Additional data
                                                  credentialPubKey_));
 }
diff --git a/identity/aidl/vts/PresentationSessionTests.cpp b/identity/aidl/vts/PresentationSessionTests.cpp
new file mode 100644
index 0000000..88acb26
--- /dev/null
+++ b/identity/aidl/vts/PresentationSessionTests.cpp
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "PresentationSessionTests"
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/keymaster/HardwareAuthToken.h>
+#include <aidl/android/hardware/keymaster/VerificationToken.h>
+#include <android-base/logging.h>
+#include <android/hardware/identity/IIdentityCredentialStore.h>
+#include <android/hardware/identity/support/IdentityCredentialSupport.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <cppbor.h>
+#include <cppbor_parse.h>
+#include <gtest/gtest.h>
+#include <future>
+#include <map>
+#include <utility>
+
+#include "Util.h"
+
+namespace android::hardware::identity {
+
+using std::endl;
+using std::make_pair;
+using std::map;
+using std::optional;
+using std::pair;
+using std::string;
+using std::tie;
+using std::vector;
+
+using ::android::sp;
+using ::android::String16;
+using ::android::binder::Status;
+
+using ::android::hardware::keymaster::HardwareAuthToken;
+using ::android::hardware::keymaster::VerificationToken;
+
+class PresentationSessionTests : public testing::TestWithParam<string> {
+  public:
+    virtual void SetUp() override {
+        credentialStore_ = android::waitForDeclaredService<IIdentityCredentialStore>(
+                String16(GetParam().c_str()));
+        ASSERT_NE(credentialStore_, nullptr);
+        halApiVersion_ = credentialStore_->getInterfaceVersion();
+    }
+
+    void provisionData();
+
+    void provisionSingleDocument(const string& docType, vector<uint8_t>* outCredentialData,
+                                 vector<uint8_t>* outCredentialPubKey);
+
+    // Set by provisionData
+    vector<uint8_t> credential1Data_;
+    vector<uint8_t> credential1PubKey_;
+    vector<uint8_t> credential2Data_;
+    vector<uint8_t> credential2PubKey_;
+
+    sp<IIdentityCredentialStore> credentialStore_;
+    int halApiVersion_;
+};
+
+void PresentationSessionTests::provisionData() {
+    provisionSingleDocument("org.iso.18013-5.2019.mdl", &credential1Data_, &credential1PubKey_);
+    provisionSingleDocument("org.blah.OtherhDocTypeXX", &credential2Data_, &credential2PubKey_);
+}
+
+void PresentationSessionTests::provisionSingleDocument(const string& docType,
+                                                       vector<uint8_t>* outCredentialData,
+                                                       vector<uint8_t>* outCredentialPubKey) {
+    bool testCredential = true;
+    sp<IWritableIdentityCredential> wc;
+    ASSERT_TRUE(credentialStore_->createCredential(docType, testCredential, &wc).isOk());
+
+    vector<uint8_t> attestationApplicationId;
+    vector<uint8_t> attestationChallenge = {1};
+    vector<Certificate> certChain;
+    ASSERT_TRUE(wc->getAttestationCertificate(attestationApplicationId, attestationChallenge,
+                                              &certChain)
+                        .isOk());
+
+    optional<vector<uint8_t>> optCredentialPubKey =
+            support::certificateChainGetTopMostKey(certChain[0].encodedCertificate);
+    ASSERT_TRUE(optCredentialPubKey);
+    *outCredentialPubKey = optCredentialPubKey.value();
+
+    size_t proofOfProvisioningSize = 106;
+    // Not in v1 HAL, may fail
+    wc->setExpectedProofOfProvisioningSize(proofOfProvisioningSize);
+
+    ASSERT_TRUE(wc->startPersonalization(1 /* numAccessControlProfiles */,
+                                         {1} /* numDataElementsPerNamespace */)
+                        .isOk());
+
+    // Access control profile 0: open access - don't care about the returned SACP
+    SecureAccessControlProfile sacp;
+    ASSERT_TRUE(wc->addAccessControlProfile(1, {}, false, 0, 0, &sacp).isOk());
+
+    // Single entry - don't care about the returned encrypted data
+    ASSERT_TRUE(wc->beginAddEntry({1}, "ns", "Some Data", 1).isOk());
+    vector<uint8_t> encryptedData;
+    ASSERT_TRUE(wc->addEntryValue({9}, &encryptedData).isOk());
+
+    vector<uint8_t> proofOfProvisioningSignature;
+    Status status = wc->finishAddingEntries(outCredentialData, &proofOfProvisioningSignature);
+    EXPECT_TRUE(status.isOk()) << status.exceptionCode() << ": " << status.exceptionMessage();
+}
+
+// This checks that any methods called on an IIdentityCredential obtained via a session
+// returns STATUS_FAILED except for startRetrieval(), startRetrieveEntryValue(),
+// retrieveEntryValue(), finishRetrieval(), setRequestedNamespaces(), setVerificationToken()
+//
+TEST_P(PresentationSessionTests, returnsFailureOnUnsupportedMethods) {
+    if (halApiVersion_ < 4) {
+        GTEST_SKIP() << "Need HAL API version 4, have " << halApiVersion_;
+    }
+
+    provisionData();
+
+    sp<IPresentationSession> session;
+    ASSERT_TRUE(credentialStore_
+                        ->createPresentationSession(
+                                CipherSuite::CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256,
+                                &session)
+                        .isOk());
+
+    sp<IIdentityCredential> credential;
+    ASSERT_TRUE(session->getCredential(credential1Data_, &credential).isOk());
+
+    Status result;
+
+    vector<uint8_t> signatureProofOfDeletion;
+    result = credential->deleteCredential(&signatureProofOfDeletion);
+    EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
+    EXPECT_EQ(IIdentityCredentialStore::STATUS_FAILED, result.serviceSpecificErrorCode());
+
+    vector<uint8_t> ephemeralKeyPair;
+    result = credential->createEphemeralKeyPair(&ephemeralKeyPair);
+    EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
+    EXPECT_EQ(IIdentityCredentialStore::STATUS_FAILED, result.serviceSpecificErrorCode());
+
+    result = credential->setReaderEphemeralPublicKey({});
+    EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
+    EXPECT_EQ(IIdentityCredentialStore::STATUS_FAILED, result.serviceSpecificErrorCode());
+
+    int64_t authChallenge;
+    result = credential->createAuthChallenge(&authChallenge);
+    EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
+    EXPECT_EQ(IIdentityCredentialStore::STATUS_FAILED, result.serviceSpecificErrorCode());
+
+    Certificate certificate;
+    vector<uint8_t> signingKeyBlob;
+    result = credential->generateSigningKeyPair(&signingKeyBlob, &certificate);
+    EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
+    EXPECT_EQ(IIdentityCredentialStore::STATUS_FAILED, result.serviceSpecificErrorCode());
+
+    result = credential->deleteCredentialWithChallenge({}, &signatureProofOfDeletion);
+    EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
+    EXPECT_EQ(IIdentityCredentialStore::STATUS_FAILED, result.serviceSpecificErrorCode());
+
+    vector<uint8_t> signatureProofOfOwnership;
+    result = credential->proveOwnership({}, &signatureProofOfOwnership);
+    EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
+    EXPECT_EQ(IIdentityCredentialStore::STATUS_FAILED, result.serviceSpecificErrorCode());
+
+    sp<IWritableIdentityCredential> writableCredential;
+    result = credential->updateCredential(&writableCredential);
+    EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
+    EXPECT_EQ(IIdentityCredentialStore::STATUS_FAILED, result.serviceSpecificErrorCode());
+}
+
+// TODO: need to add tests to check that the returned IIdentityCredential works
+//       as intended.
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PresentationSessionTests);
+INSTANTIATE_TEST_SUITE_P(
+        Identity, PresentationSessionTests,
+        testing::ValuesIn(android::getAidlHalInstanceNames(IIdentityCredentialStore::descriptor)),
+        android::PrintInstanceNameToString);
+
+}  // namespace android::hardware::identity
diff --git a/identity/aidl/vts/ProveOwnershipTests.cpp b/identity/aidl/vts/ProveOwnershipTests.cpp
index c622193..f8ec670 100644
--- a/identity/aidl/vts/ProveOwnershipTests.cpp
+++ b/identity/aidl/vts/ProveOwnershipTests.cpp
@@ -125,14 +125,22 @@
                                 credentialData_, &credential)
                         .isOk());
 
-    vector<uint8_t> challenge = {17, 18};
+    // Implementations must support at least 32 bytes.
+    string challengeString = "0123456789abcdef0123456789abcdef";
+    vector<uint8_t> challenge(challengeString.begin(), challengeString.end());
     vector<uint8_t> proofOfOwnershipSignature;
     ASSERT_TRUE(credential->proveOwnership(challenge, &proofOfOwnershipSignature).isOk());
     optional<vector<uint8_t>> proofOfOwnership =
             support::coseSignGetPayload(proofOfOwnershipSignature);
     ASSERT_TRUE(proofOfOwnership);
     string cborPretty = cppbor::prettyPrint(proofOfOwnership.value(), 32, {});
-    EXPECT_EQ("['ProofOfOwnership', 'org.iso.18013-5.2019.mdl', {0x11, 0x12}, true, ]", cborPretty);
+    EXPECT_EQ(
+            "['ProofOfOwnership', 'org.iso.18013-5.2019.mdl', {"
+            "0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, "
+            "0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, "
+            "0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, "
+            "0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66}, true, ]",
+            cborPretty);
     EXPECT_TRUE(support::coseCheckEcDsaSignature(proofOfOwnershipSignature, {},  // Additional data
                                                  credentialPubKey_));
 }
diff --git a/identity/aidl/vts/Util.cpp b/identity/aidl/vts/Util.cpp
index 1148cb0..f3d7c30 100644
--- a/identity/aidl/vts/Util.cpp
+++ b/identity/aidl/vts/Util.cpp
@@ -20,12 +20,16 @@
 
 #include <android-base/logging.h>
 
+#include <KeyMintAidlTestBase.h>
 #include <aidl/Gtest.h>
+#include <aidl/android/hardware/security/keymint/MacedPublicKey.h>
 #include <android-base/stringprintf.h>
 #include <keymaster/km_openssl/openssl_utils.h>
 #include <keymasterV4_1/attestation_record.h>
-#include <charconv>
+#include <keymint_support/openssl_utils.h>
+#include <openssl/evp.h>
 
+#include <charconv>
 #include <map>
 
 namespace android::hardware::identity::test_utils {
@@ -36,10 +40,13 @@
 using std::string;
 using std::vector;
 
+using ::aidl::android::hardware::security::keymint::test::check_maced_pubkey;
+using ::aidl::android::hardware::security::keymint::test::p256_pub_key;
 using ::android::sp;
 using ::android::String16;
 using ::android::base::StringPrintf;
 using ::android::binder::Status;
+using ::android::hardware::security::keymint::MacedPublicKey;
 using ::keymaster::X509_Ptr;
 
 bool setupWritableCredential(sp<IWritableIdentityCredential>& writableCredential,
@@ -58,6 +65,77 @@
     }
 }
 
+optional<vector<vector<uint8_t>>> createFakeRemotelyProvisionedCertificateChain(
+        const MacedPublicKey& macedPublicKey) {
+    // The helper library uses the NDK symbols, so play a little trickery here to convert
+    // the data into the proper type so we can reuse the helper function to get the pubkey.
+    ::aidl::android::hardware::security::keymint::MacedPublicKey ndkMacedPublicKey;
+    ndkMacedPublicKey.macedKey = macedPublicKey.macedKey;
+
+    vector<uint8_t> publicKeyBits;
+    check_maced_pubkey(ndkMacedPublicKey, /*testMode=*/true, &publicKeyBits);
+
+    ::aidl::android::hardware::security::keymint::EVP_PKEY_Ptr publicKey;
+    p256_pub_key(publicKeyBits, &publicKey);
+
+    // Generate an arbitrary root key for our chain
+    bssl::UniquePtr<EC_KEY> ecRootKey(EC_KEY_new());
+    bssl::UniquePtr<EVP_PKEY> rootKey(EVP_PKEY_new());
+    if (ecRootKey.get() == nullptr || rootKey.get() == nullptr) {
+        LOG(ERROR) << "Memory allocation failed";
+        return {};
+    }
+
+    bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
+    if (group.get() == nullptr) {
+        LOG(ERROR) << "Error creating EC group by curve name";
+        return {};
+    }
+
+    if (EC_KEY_set_group(ecRootKey.get(), group.get()) != 1 ||
+        EC_KEY_generate_key(ecRootKey.get()) != 1 || EC_KEY_check_key(ecRootKey.get()) < 0) {
+        LOG(ERROR) << "Error generating key";
+        return {};
+    }
+
+    if (EVP_PKEY_set1_EC_KEY(rootKey.get(), ecRootKey.get()) != 1) {
+        LOG(ERROR) << "Error getting private key";
+        return {};
+    }
+
+    // The VTS test does not fully validate the chain, so we're ok without the proper CA extensions.
+    map<string, vector<uint8_t>> extensions;
+
+    // Now make a self-signed cert
+    optional<vector<uint8_t>> root = support::ecPublicKeyGenerateCertificate(
+            rootKey.get(), rootKey.get(),
+            /*serialDecimal=*/"31415",
+            /*subject=*/"Android IdentityCredential VTS Test Root Certificate",
+            /*subject=*/"Android IdentityCredential VTS Test Root Certificate",
+            /*validityNotBefore=*/time(nullptr),
+            /*validityNotAfter=*/time(nullptr) + 365 * 24 * 3600, extensions);
+    if (!root) {
+        LOG(ERROR) << "Error generating root cert";
+        return std::nullopt;
+    }
+
+    // Now sign a CA cert so that we have a chain that's good enough to satisfy
+    // the VTS tests.
+    optional<vector<uint8_t>> intermediate = support::ecPublicKeyGenerateCertificate(
+            publicKey.get(), rootKey.get(),
+            /*serialDecimal=*/"42",
+            /*subject=*/"Android IdentityCredential VTS Test Root Certificate",
+            /*subject=*/"Android IdentityCredential VTS Test Attestation Certificate",
+            /*validityNotBefore=*/time(nullptr),
+            /*validityNotAfter=*/time(nullptr) + 365 * 24 * 3600, extensions);
+    if (!intermediate) {
+        LOG(ERROR) << "Error generating intermediate cert";
+        return std::nullopt;
+    }
+
+    return vector<vector<uint8_t>>{std::move(*intermediate), std::move(*root)};
+}
+
 optional<vector<uint8_t>> generateReaderCertificate(string serialDecimal) {
     vector<uint8_t> privKey;
     return generateReaderCertificate(serialDecimal, &privKey);
diff --git a/identity/aidl/vts/Util.h b/identity/aidl/vts/Util.h
index 80e52a2..b120dc9 100644
--- a/identity/aidl/vts/Util.h
+++ b/identity/aidl/vts/Util.h
@@ -19,6 +19,7 @@
 
 #include <android/hardware/identity/IIdentityCredentialStore.h>
 #include <android/hardware/identity/support/IdentityCredentialSupport.h>
+#include <android/hardware/security/keymint/MacedPublicKey.h>
 #include <cppbor.h>
 #include <cppbor_parse.h>
 #include <gtest/gtest.h>
@@ -97,6 +98,9 @@
 bool setupWritableCredential(sp<IWritableIdentityCredential>& writableCredential,
                              sp<IIdentityCredentialStore>& credentialStore, bool testCredential);
 
+optional<vector<vector<uint8_t>>> createFakeRemotelyProvisionedCertificateChain(
+        const ::android::hardware::security::keymint::MacedPublicKey& macedPublicKey);
+
 optional<vector<uint8_t>> generateReaderCertificate(string serialDecimal);
 
 optional<vector<uint8_t>> generateReaderCertificate(string serialDecimal,
diff --git a/identity/aidl/vts/VtsAttestationTests.cpp b/identity/aidl/vts/VtsAttestationTests.cpp
index e12fe05..7caa259 100644
--- a/identity/aidl/vts/VtsAttestationTests.cpp
+++ b/identity/aidl/vts/VtsAttestationTests.cpp
@@ -66,7 +66,8 @@
     ASSERT_TRUE(setupWritableCredential(writableCredential, credentialStore_,
                                         false /* testCredential */));
 
-    string challenge = "NotSoRandomChallenge1NotSoRandomChallenge1NotSoRandomChallenge1";
+    // Must support at least 32 bytes.
+    string challenge = "0123456789abcdef0123456789abcdef";
     vector<uint8_t> attestationChallenge(challenge.begin(), challenge.end());
     vector<Certificate> attestationCertificate;
     string applicationId = "Attestation Verification";
diff --git a/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp b/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
index bc37020..94d4c88 100644
--- a/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
+++ b/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
@@ -18,6 +18,8 @@
 
 #include <aidl/Gtest.h>
 #include <aidl/Vintf.h>
+#include <aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.h>
+#include <aidl/android/hardware/security/keymint/MacedPublicKey.h>
 #include <android-base/logging.h>
 #include <android/hardware/identity/IIdentityCredentialStore.h>
 #include <android/hardware/identity/support/IdentityCredentialSupport.h>
@@ -42,6 +44,8 @@
 using ::android::sp;
 using ::android::String16;
 using ::android::binder::Status;
+using ::android::hardware::security::keymint::IRemotelyProvisionedComponent;
+using ::android::hardware::security::keymint::MacedPublicKey;
 
 class IdentityCredentialTests : public testing::TestWithParam<string> {
   public:
@@ -101,6 +105,103 @@
                                                attestationApplicationId, false);
 }
 
+TEST_P(IdentityCredentialTests, verifyAttestationSuccessWithRemoteProvisioning) {
+    HardwareInformation hwInfo;
+    ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
+
+    if (!hwInfo.isRemoteKeyProvisioningSupported) {
+        GTEST_SKIP() << "Remote provisioning is not supported";
+    }
+
+    Status result;
+
+    sp<IWritableIdentityCredential> writableCredential;
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+                                                    false /* testCredential */));
+
+    sp<IRemotelyProvisionedComponent> rpc;
+    result = credentialStore_->getRemotelyProvisionedComponent(&rpc);
+    ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage();
+
+    MacedPublicKey macedPublicKey;
+    std::vector<uint8_t> attestationKey;
+    result = rpc->generateEcdsaP256KeyPair(/*testMode=*/true, &macedPublicKey, &attestationKey);
+    ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage();
+
+    optional<vector<vector<uint8_t>>> remotelyProvisionedCertChain =
+            test_utils::createFakeRemotelyProvisionedCertificateChain(macedPublicKey);
+    ASSERT_TRUE(remotelyProvisionedCertChain);
+
+    vector<uint8_t> concatenatedCerts;
+    for (const vector<uint8_t>& cert : *remotelyProvisionedCertChain) {
+        concatenatedCerts.insert(concatenatedCerts.end(), cert.begin(), cert.end());
+    }
+    result = writableCredential->setRemotelyProvisionedAttestationKey(attestationKey,
+                                                                      concatenatedCerts);
+    ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage();
+
+    string challenge = "NotSoRandomChallenge1NotSoRandomChallenge1NotSoRandomChallenge1";
+    vector<uint8_t> attestationChallenge(challenge.begin(), challenge.end());
+    vector<Certificate> attestationCertificate;
+    vector<uint8_t> attestationApplicationId = {1};
+
+    result = writableCredential->getAttestationCertificate(
+            attestationApplicationId, attestationChallenge, &attestationCertificate);
+
+    ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage();
+
+    test_utils::validateAttestationCertificate(attestationCertificate, attestationChallenge,
+                                               attestationApplicationId, false);
+
+    ASSERT_EQ(remotelyProvisionedCertChain->size() + 1, attestationCertificate.size());
+    for (size_t i = 0; i < remotelyProvisionedCertChain->size(); ++i) {
+        ASSERT_EQ(remotelyProvisionedCertChain->at(i),
+                  attestationCertificate[i + 1].encodedCertificate)
+                << "Certificate mismatch (cert index " << i + 1 << " out of "
+                << attestationCertificate.size() << " total certs)";
+    }
+}
+
+TEST_P(IdentityCredentialTests, verifyRemotelyProvisionedKeyMayOnlyBeSetOnce) {
+    HardwareInformation hwInfo;
+    ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
+
+    if (!hwInfo.isRemoteKeyProvisioningSupported) {
+        GTEST_SKIP() << "Remote provisioning is not supported";
+    }
+
+    sp<IRemotelyProvisionedComponent> rpc;
+    Status result = credentialStore_->getRemotelyProvisionedComponent(&rpc);
+    ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage();
+
+    MacedPublicKey macedPublicKey;
+    std::vector<uint8_t> attestationKey;
+    result = rpc->generateEcdsaP256KeyPair(/*testMode=*/true, &macedPublicKey, &attestationKey);
+    ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage();
+
+    optional<vector<vector<uint8_t>>> remotelyProvisionedCertChain =
+            test_utils::createFakeRemotelyProvisionedCertificateChain(macedPublicKey);
+    ASSERT_TRUE(remotelyProvisionedCertChain);
+
+    vector<uint8_t> concatenatedCerts;
+    for (const vector<uint8_t>& cert : *remotelyProvisionedCertChain) {
+        concatenatedCerts.insert(concatenatedCerts.end(), cert.begin(), cert.end());
+    }
+
+    sp<IWritableIdentityCredential> writableCredential;
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+                                                    /*testCredential=*/false));
+
+    result = writableCredential->setRemotelyProvisionedAttestationKey(attestationKey,
+                                                                      concatenatedCerts);
+    ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage();
+
+    // Now try again, and verify that the implementation rejects it.
+    result = writableCredential->setRemotelyProvisionedAttestationKey(attestationKey,
+                                                                      concatenatedCerts);
+    EXPECT_FALSE(result.isOk());
+}
+
 TEST_P(IdentityCredentialTests, verifyAttestationDoubleCallFails) {
     Status result;
 
diff --git a/identity/support/Android.bp b/identity/support/Android.bp
index db1a945..4e3d1f7 100644
--- a/identity/support/Android.bp
+++ b/identity/support/Android.bp
@@ -86,6 +86,9 @@
 
 cc_test {
     name: "cppbor_test",
+    tidy_timeout_srcs: [
+        "tests/cppbor_test.cpp",
+    ],
     srcs: [
         "tests/cppbor_test.cpp",
     ],
@@ -101,6 +104,9 @@
 
 cc_test_host {
     name: "cppbor_host_test",
+    tidy_timeout_srcs: [
+        "tests/cppbor_test.cpp",
+    ],
     srcs: [
         "tests/cppbor_test.cpp",
     ],
diff --git a/identity/support/include/android/hardware/identity/support/IdentityCredentialSupport.h b/identity/support/include/android/hardware/identity/support/IdentityCredentialSupport.h
index 3b91de6..952b69a 100644
--- a/identity/support/include/android/hardware/identity/support/IdentityCredentialSupport.h
+++ b/identity/support/include/android/hardware/identity/support/IdentityCredentialSupport.h
@@ -17,6 +17,8 @@
 #ifndef IDENTITY_SUPPORT_INCLUDE_IDENTITY_CREDENTIAL_UTILS_H_
 #define IDENTITY_SUPPORT_INCLUDE_IDENTITY_CREDENTIAL_UTILS_H_
 
+#include <openssl/evp.h>
+
 #include <cstdint>
 #include <map>
 #include <optional>
@@ -128,6 +130,15 @@
         const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId,
         bool isTestCredential);
 
+// Alternate version of createEcKeyPairAndAttestation that accepts an attestation key
+// blob to sign the generated key. Only a single certificate is returned, rather than
+// a full chain.
+//
+optional<std::pair<vector<uint8_t>, vector<uint8_t>>> createEcKeyPairWithAttestationKey(
+        const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId,
+        const vector<uint8_t>& attestationKeyBlob, const vector<uint8_t>& attestationKeyCert,
+        bool isTestCredential);
+
 // (TODO: remove when no longer used by 3rd party.)
 optional<vector<vector<uint8_t>>> createAttestationForEcPublicKey(
         const vector<uint8_t>& publicKey, const vector<uint8_t>& challenge,
@@ -240,6 +251,13 @@
         time_t validityNotBefore, time_t validityNotAfter,
         const map<string, vector<uint8_t>>& extensions);
 
+// Identical behavior to the above version of ecPublicKeyGenerateCertificate, except this
+// overload takes OpenSSL key parameters instead of key bitstrings as inputs.
+optional<vector<uint8_t>> ecPublicKeyGenerateCertificate(
+        EVP_PKEY* publicKey, EVP_PKEY* signingKey, const string& serialDecimal,
+        const string& issuer, const string& subject, time_t validityNotBefore,
+        time_t validityNotAfter, const map<string, vector<uint8_t>>& extensions);
+
 // Performs Elliptic-curve Diffie-Helman using |publicKey| (which must be in the
 // format returned by ecKeyPairGetPublicKey()) and |privateKey| (which must be
 // in the format returned by ecKeyPairGetPrivateKey()).
@@ -389,6 +407,10 @@
 // may be smaller than |maxChunkSize|.
 vector<vector<uint8_t>> chunkVector(const vector<uint8_t>& content, size_t maxChunkSize);
 
+// Extract the issuer subject name from the leaf cert in the given chain,
+// returning it as DER-encoded bytes.
+optional<vector<uint8_t>> extractDerSubjectFromCertificate(const vector<uint8_t>& certificate);
+
 }  // namespace support
 }  // namespace identity
 }  // namespace hardware
diff --git a/identity/support/include/cppbor/cppbor.h b/identity/support/include/cppbor/cppbor.h
index a755db1..af5d82e 100644
--- a/identity/support/include/cppbor/cppbor.h
+++ b/identity/support/include/cppbor/cppbor.h
@@ -274,7 +274,7 @@
     virtual std::unique_ptr<Item> clone() const override { return std::make_unique<Nint>(mValue); }
 
   private:
-    uint64_t addlInfo() const { return -1ll - mValue; }
+    uint64_t addlInfo() const { return -1LL - mValue; }
 
     int64_t mValue;
 };
diff --git a/identity/support/src/IdentityCredentialSupport.cpp b/identity/support/src/IdentityCredentialSupport.cpp
index 7f4674d..4c2f186 100644
--- a/identity/support/src/IdentityCredentialSupport.cpp
+++ b/identity/support/src/IdentityCredentialSupport.cpp
@@ -54,6 +54,7 @@
 #include <keymaster/contexts/pure_soft_keymaster_context.h>
 #include <keymaster/contexts/soft_attestation_cert.h>
 #include <keymaster/keymaster_tags.h>
+#include <keymaster/km_openssl/asymmetric_key.h>
 #include <keymaster/km_openssl/attestation_utils.h>
 #include <keymaster/km_openssl/certificate_utils.h>
 
@@ -168,6 +169,254 @@
 using X509_NAME_Ptr = bssl::UniquePtr<X509_NAME>;
 using X509_EXTENSION_Ptr = bssl::UniquePtr<X509_EXTENSION>;
 
+namespace {
+
+EVP_PKEY_Ptr generateP256Key() {
+    EC_KEY_Ptr ec_key(EC_KEY_new());
+    EVP_PKEY_Ptr pkey(EVP_PKEY_new());
+    EC_GROUP_Ptr group(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
+
+    if (ec_key.get() == nullptr || pkey.get() == nullptr) {
+        LOG(ERROR) << "Memory allocation failed";
+        return {};
+    }
+
+    if (EC_KEY_set_group(ec_key.get(), group.get()) != 1 ||
+        EC_KEY_generate_key(ec_key.get()) != 1 || EC_KEY_check_key(ec_key.get()) < 0) {
+        LOG(ERROR) << "Error generating key";
+        return {};
+    }
+
+    if (EVP_PKEY_set1_EC_KEY(pkey.get(), ec_key.get()) != 1) {
+        LOG(ERROR) << "Error getting private key";
+        return {};
+    }
+
+    return pkey;
+}
+
+optional<vector<uint8_t>> derEncodeKeyPair(const EVP_PKEY& pkey) {
+    int size = i2d_PrivateKey(&pkey, nullptr);
+    if (size == 0) {
+        LOG(ERROR) << "Error generating public key encoding";
+        return std::nullopt;
+    }
+
+    vector<uint8_t> keyPair(size);
+    unsigned char* p = keyPair.data();
+    i2d_PrivateKey(&pkey, &p);
+
+    return keyPair;
+}
+
+// Generates the attestation certificate with the parameters passed in.  Note
+// that the passed in |activeTimeMilliSeconds| |expireTimeMilliSeconds| are in
+// milli seconds since epoch.  We are setting them to milliseconds due to
+// requirement in AuthorizationSet KM_DATE fields.  The certificate created is
+// actually in seconds.
+//
+optional<vector<vector<uint8_t>>> signAttestationCertificate(
+        const ::keymaster::PureSoftKeymasterContext& context, const EVP_PKEY* key,
+        const vector<uint8_t>& applicationId, const vector<uint8_t>& challenge,
+        const vector<uint8_t>& attestationKeyBlob,
+        const vector<uint8_t>& derAttestationCertSubjectName, uint64_t activeTimeMilliSeconds,
+        uint64_t expireTimeMilliSeconds, bool isTestCredential) {
+    ::keymaster::X509_NAME_Ptr subjectName;
+    if (KM_ERROR_OK !=
+        ::keymaster::make_name_from_str("Android Identity Credential Key", &subjectName)) {
+        LOG(ERROR) << "Cannot create attestation subject";
+        return {};
+    }
+
+    vector<uint8_t> subject(i2d_X509_NAME(subjectName.get(), NULL));
+    unsigned char* subjectPtr = subject.data();
+
+    i2d_X509_NAME(subjectName.get(), &subjectPtr);
+
+    ::keymaster::AuthorizationSet auth_set(
+            ::keymaster::AuthorizationSetBuilder()
+                    .Authorization(::keymaster::TAG_CERTIFICATE_NOT_BEFORE, activeTimeMilliSeconds)
+                    .Authorization(::keymaster::TAG_CERTIFICATE_NOT_AFTER, expireTimeMilliSeconds)
+                    .Authorization(::keymaster::TAG_ATTESTATION_CHALLENGE, challenge.data(),
+                                   challenge.size())
+                    .Authorization(::keymaster::TAG_ACTIVE_DATETIME, activeTimeMilliSeconds)
+                    // Even though identity attestation hal said the application
+                    // id should be in software enforced authentication set,
+                    // keymaster portable lib expect the input in this
+                    // parameter because the software enforced in input to keymaster
+                    // refers to the key software enforced properties. And this
+                    // parameter refers to properties of the attestation which
+                    // includes app id.
+                    .Authorization(::keymaster::TAG_ATTESTATION_APPLICATION_ID,
+                                   applicationId.data(), applicationId.size())
+                    .Authorization(::keymaster::TAG_CERTIFICATE_SUBJECT, subject.data(),
+                                   subject.size())
+                    .Authorization(::keymaster::TAG_USAGE_EXPIRE_DATETIME, expireTimeMilliSeconds));
+
+    // Unique id and device id is not applicable for identity credential attestation,
+    // so we don't need to set those or application id.
+    ::keymaster::AuthorizationSet swEnforced(::keymaster::AuthorizationSetBuilder().Authorization(
+            ::keymaster::TAG_CREATION_DATETIME, activeTimeMilliSeconds));
+
+    ::keymaster::AuthorizationSetBuilder hwEnforcedBuilder =
+            ::keymaster::AuthorizationSetBuilder()
+                    .Authorization(::keymaster::TAG_PURPOSE, KM_PURPOSE_SIGN)
+                    .Authorization(::keymaster::TAG_KEY_SIZE, 256)
+                    .Authorization(::keymaster::TAG_ALGORITHM, KM_ALGORITHM_EC)
+                    .Authorization(::keymaster::TAG_NO_AUTH_REQUIRED)
+                    .Authorization(::keymaster::TAG_DIGEST, KM_DIGEST_SHA_2_256)
+                    .Authorization(::keymaster::TAG_EC_CURVE, KM_EC_CURVE_P_256)
+                    .Authorization(::keymaster::TAG_OS_VERSION, 42)
+                    .Authorization(::keymaster::TAG_OS_PATCHLEVEL, 43);
+
+    // Only include TAG_IDENTITY_CREDENTIAL_KEY if it's not a test credential
+    if (!isTestCredential) {
+        hwEnforcedBuilder.Authorization(::keymaster::TAG_IDENTITY_CREDENTIAL_KEY);
+    }
+    ::keymaster::AuthorizationSet hwEnforced(hwEnforcedBuilder);
+
+    keymaster_error_t error;
+    ::keymaster::AttestKeyInfo attestKeyInfo;
+    ::keymaster::KeymasterBlob issuerSubjectNameBlob;
+    if (!attestationKeyBlob.empty()) {
+        ::keymaster::KeymasterKeyBlob blob(attestationKeyBlob.data(), attestationKeyBlob.size());
+        ::keymaster::UniquePtr<::keymaster::Key> parsedKey;
+        error = context.ParseKeyBlob(blob, /*additional_params=*/{}, &parsedKey);
+        if (error != KM_ERROR_OK) {
+            LOG(ERROR) << "Error loading attestation key: " << error;
+            return std::nullopt;
+        }
+
+        attestKeyInfo.signing_key =
+                static_cast<::keymaster::AsymmetricKey&>(*parsedKey).InternalToEvp();
+        issuerSubjectNameBlob = ::keymaster::KeymasterBlob(derAttestationCertSubjectName.data(),
+                                                           derAttestationCertSubjectName.size());
+        attestKeyInfo.issuer_subject = &issuerSubjectNameBlob;
+    }
+
+    ::keymaster::CertificateChain certChain = generate_attestation(
+            key, swEnforced, hwEnforced, auth_set, std::move(attestKeyInfo), context, &error);
+
+    if (KM_ERROR_OK != error) {
+        LOG(ERROR) << "Error generating attestation from EVP key: " << error;
+        return std::nullopt;
+    }
+
+    vector<vector<uint8_t>> vectors(certChain.entry_count);
+    for (std::size_t i = 0; i < certChain.entry_count; i++) {
+        vectors[i] = {certChain.entries[i].data,
+                      certChain.entries[i].data + certChain.entries[i].data_length};
+    }
+    return vectors;
+}
+
+int parseDigits(const char** s, int numDigits) {
+    int result;
+    auto [_, ec] = std::from_chars(*s, *s + numDigits, result);
+    if (ec != std::errc()) {
+        LOG(ERROR) << "Error parsing " << numDigits << " digits "
+                   << " from " << s;
+        return 0;
+    }
+    *s += numDigits;
+    return result;
+}
+
+bool parseAsn1Time(const ASN1_TIME* asn1Time, time_t* outTime) {
+    struct tm tm;
+
+    memset(&tm, '\0', sizeof(tm));
+    const char* timeStr = (const char*)asn1Time->data;
+    const char* s = timeStr;
+    if (asn1Time->type == V_ASN1_UTCTIME) {
+        tm.tm_year = parseDigits(&s, 2);
+        if (tm.tm_year < 70) {
+            tm.tm_year += 100;
+        }
+    } else if (asn1Time->type == V_ASN1_GENERALIZEDTIME) {
+        tm.tm_year = parseDigits(&s, 4) - 1900;
+        tm.tm_year -= 1900;
+    } else {
+        LOG(ERROR) << "Unsupported ASN1_TIME type " << asn1Time->type;
+        return false;
+    }
+    tm.tm_mon = parseDigits(&s, 2) - 1;
+    tm.tm_mday = parseDigits(&s, 2);
+    tm.tm_hour = parseDigits(&s, 2);
+    tm.tm_min = parseDigits(&s, 2);
+    tm.tm_sec = parseDigits(&s, 2);
+    // This may need to be updated if someone create certificates using +/- instead of Z.
+    //
+    if (*s != 'Z') {
+        LOG(ERROR) << "Expected Z in string '" << timeStr << "' at offset " << (s - timeStr);
+        return false;
+    }
+
+    time_t t = timegm(&tm);
+    if (t == -1) {
+        LOG(ERROR) << "Error converting broken-down time to time_t";
+        return false;
+    }
+    *outTime = t;
+    return true;
+}
+
+optional<uint64_t> getCertificateExpiryAsMillis(const uint8_t* derCert, size_t derCertSize) {
+    X509_Ptr x509Cert(d2i_X509(nullptr, &derCert, derCertSize));
+    if (!x509Cert) {
+        LOG(ERROR) << "Error parsing certificate";
+        return std::nullopt;
+    }
+
+    time_t notAfter;
+    if (!parseAsn1Time(X509_get0_notAfter(x509Cert.get()), &notAfter)) {
+        LOG(ERROR) << "Error getting notAfter from batch certificate";
+        return std::nullopt;
+    }
+
+    return notAfter * 1000;
+}
+
+optional<vector<vector<uint8_t>>> createAttestation(EVP_PKEY* pkey,
+                                                    const vector<uint8_t>& challenge,
+                                                    const vector<uint8_t>& applicationId,
+                                                    bool isTestCredential) {
+    // Pretend to be implemented in a trusted environment just so we can pass
+    // the VTS tests. Of course, this is a pretend-only game since hopefully no
+    // relying party is ever going to trust our batch key and those keys above
+    // it.
+    ::keymaster::PureSoftKeymasterContext context(::keymaster::KmVersion::KEYMINT_1,
+                                                  KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT);
+
+    keymaster_error_t error;
+    ::keymaster::CertificateChain attestation_chain =
+            context.GetAttestationChain(KM_ALGORITHM_EC, &error);
+    if (KM_ERROR_OK != error) {
+        LOG(ERROR) << "Error getting attestation chain " << error;
+        return std::nullopt;
+    }
+
+    if (attestation_chain.entry_count < 1) {
+        LOG(ERROR) << "Expected at least one entry in attestation chain";
+        return std::nullopt;
+    }
+
+    uint64_t activeTimeMs = time(nullptr) * 1000;
+    optional<uint64_t> expireTimeMs = getCertificateExpiryAsMillis(
+            attestation_chain.entries[0].data, attestation_chain.entries[0].data_length);
+    if (!expireTimeMs) {
+        LOG(ERROR) << "Error getting expiration time for batch cert";
+        return std::nullopt;
+    }
+
+    return signAttestationCertificate(context, pkey, applicationId, challenge,
+                                      /*attestationKeyBlob=*/{},
+                                      /*derAttestationCertSubjectName=*/{}, activeTimeMs,
+                                      *expireTimeMs, isTestCredential);
+}
+
+}  // namespace
+
 // bool getRandom(size_t numBytes, vector<uint8_t>& output) {
 optional<vector<uint8_t>> getRandom(size_t numBytes) {
     vector<uint8_t> output;
@@ -577,69 +826,30 @@
     return hmac;
 }
 
-int parseDigits(const char** s, int numDigits) {
-    int result;
-    auto [_, ec] = std::from_chars(*s, *s + numDigits, result);
-    if (ec != std::errc()) {
-        LOG(ERROR) << "Error parsing " << numDigits << " digits "
-                   << " from " << s;
-        return 0;
+optional<std::pair<vector<uint8_t>, vector<vector<uint8_t>>>> createEcKeyPairAndAttestation(
+        const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId,
+        bool isTestCredential) {
+    EVP_PKEY_Ptr pkey = generateP256Key();
+
+    optional<vector<vector<uint8_t>>> attestationCertChain =
+            createAttestation(pkey.get(), challenge, applicationId, isTestCredential);
+    if (!attestationCertChain) {
+        LOG(ERROR) << "Error create attestation from key and challenge";
+        return {};
     }
-    *s += numDigits;
-    return result;
+
+    optional<vector<uint8_t>> keyPair = derEncodeKeyPair(*pkey);
+    if (!keyPair) {
+        return std::nullopt;
+    }
+
+    return make_pair(*keyPair, *attestationCertChain);
 }
 
-bool parseAsn1Time(const ASN1_TIME* asn1Time, time_t* outTime) {
-    struct tm tm;
-
-    memset(&tm, '\0', sizeof(tm));
-    const char* timeStr = (const char*)asn1Time->data;
-    const char* s = timeStr;
-    if (asn1Time->type == V_ASN1_UTCTIME) {
-        tm.tm_year = parseDigits(&s, 2);
-        if (tm.tm_year < 70) {
-            tm.tm_year += 100;
-        }
-    } else if (asn1Time->type == V_ASN1_GENERALIZEDTIME) {
-        tm.tm_year = parseDigits(&s, 4) - 1900;
-        tm.tm_year -= 1900;
-    } else {
-        LOG(ERROR) << "Unsupported ASN1_TIME type " << asn1Time->type;
-        return false;
-    }
-    tm.tm_mon = parseDigits(&s, 2) - 1;
-    tm.tm_mday = parseDigits(&s, 2);
-    tm.tm_hour = parseDigits(&s, 2);
-    tm.tm_min = parseDigits(&s, 2);
-    tm.tm_sec = parseDigits(&s, 2);
-    // This may need to be updated if someone create certificates using +/- instead of Z.
-    //
-    if (*s != 'Z') {
-        LOG(ERROR) << "Expected Z in string '" << timeStr << "' at offset " << (s - timeStr);
-        return false;
-    }
-
-    time_t t = timegm(&tm);
-    if (t == -1) {
-        LOG(ERROR) << "Error converting broken-down time to time_t";
-        return false;
-    }
-    *outTime = t;
-    return true;
-}
-
-// Generates the attestation certificate with the parameters passed in.  Note
-// that the passed in |activeTimeMilliSeconds| |expireTimeMilliSeconds| are in
-// milli seconds since epoch.  We are setting them to milliseconds due to
-// requirement in AuthorizationSet KM_DATE fields.  The certificate created is
-// actually in seconds.
-//
-// If 0 is passed for expiration time, the expiration time from batch
-// certificate will be used.
-//
-optional<vector<vector<uint8_t>>> createAttestation(
-        const EVP_PKEY* key, const vector<uint8_t>& applicationId, const vector<uint8_t>& challenge,
-        uint64_t activeTimeMilliSeconds, uint64_t expireTimeMilliSeconds, bool isTestCredential) {
+optional<std::pair<vector<uint8_t>, vector<uint8_t>>> createEcKeyPairWithAttestationKey(
+        const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId,
+        const vector<uint8_t>& attestationKeyBlob, const vector<uint8_t>& attestationKeyCert,
+        bool isTestCredential) {
     // Pretend to be implemented in a trusted environment just so we can pass
     // the VTS tests. Of course, this is a pretend-only game since hopefully no
     // relying party is ever going to trust our batch key and those keys above
@@ -647,148 +857,45 @@
     ::keymaster::PureSoftKeymasterContext context(::keymaster::KmVersion::KEYMINT_1,
                                                   KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT);
 
-    keymaster_error_t error;
-    ::keymaster::CertificateChain attestation_chain =
-            context.GetAttestationChain(KM_ALGORITHM_EC, &error);
-    if (KM_ERROR_OK != error) {
-        LOG(ERROR) << "Error getting attestation chain " << error;
-        return {};
-    }
-    if (expireTimeMilliSeconds == 0) {
-        if (attestation_chain.entry_count < 1) {
-            LOG(ERROR) << "Expected at least one entry in attestation chain";
-            return {};
-        }
-        keymaster_blob_t* bcBlob = &(attestation_chain.entries[0]);
-        const uint8_t* bcData = bcBlob->data;
-        auto bc = X509_Ptr(d2i_X509(nullptr, &bcData, bcBlob->data_length));
-        time_t bcNotAfter;
-        if (!parseAsn1Time(X509_get0_notAfter(bc.get()), &bcNotAfter)) {
-            LOG(ERROR) << "Error getting notAfter from batch certificate";
-            return {};
-        }
-        expireTimeMilliSeconds = bcNotAfter * 1000;
+    EVP_PKEY_Ptr pkey = generateP256Key();
+
+    uint64_t validFromMs = time(nullptr) * 1000;
+    optional<uint64_t> notAfterMs =
+            getCertificateExpiryAsMillis(attestationKeyCert.data(), attestationKeyCert.size());
+    if (!notAfterMs) {
+        LOG(ERROR) << "Error getting expiration time for attestation cert";
+        return std::nullopt;
     }
 
-    ::keymaster::X509_NAME_Ptr subjectName;
-    if (KM_ERROR_OK !=
-        ::keymaster::make_name_from_str("Android Identity Credential Key", &subjectName)) {
-        LOG(ERROR) << "Cannot create attestation subject";
-        return {};
+    optional<vector<uint8_t>> derIssuerSubject =
+            support::extractDerSubjectFromCertificate(attestationKeyCert);
+    if (!derIssuerSubject) {
+        LOG(ERROR) << "Error error extracting issuer name from the given certificate chain";
+        return std::nullopt;
     }
 
-    vector<uint8_t> subject(i2d_X509_NAME(subjectName.get(), NULL));
-    unsigned char* subjectPtr = subject.data();
-
-    i2d_X509_NAME(subjectName.get(), &subjectPtr);
-
-    ::keymaster::AuthorizationSet auth_set(
-            ::keymaster::AuthorizationSetBuilder()
-                    .Authorization(::keymaster::TAG_CERTIFICATE_NOT_BEFORE, activeTimeMilliSeconds)
-                    .Authorization(::keymaster::TAG_CERTIFICATE_NOT_AFTER, expireTimeMilliSeconds)
-                    .Authorization(::keymaster::TAG_ATTESTATION_CHALLENGE, challenge.data(),
-                                   challenge.size())
-                    .Authorization(::keymaster::TAG_ACTIVE_DATETIME, activeTimeMilliSeconds)
-                    // Even though identity attestation hal said the application
-                    // id should be in software enforced authentication set,
-                    // keymaster portable lib expect the input in this
-                    // parameter because the software enforced in input to keymaster
-                    // refers to the key software enforced properties. And this
-                    // parameter refers to properties of the attestation which
-                    // includes app id.
-                    .Authorization(::keymaster::TAG_ATTESTATION_APPLICATION_ID,
-                                   applicationId.data(), applicationId.size())
-                    .Authorization(::keymaster::TAG_CERTIFICATE_SUBJECT, subject.data(),
-                                   subject.size())
-                    .Authorization(::keymaster::TAG_USAGE_EXPIRE_DATETIME, expireTimeMilliSeconds));
-
-    // Unique id and device id is not applicable for identity credential attestation,
-    // so we don't need to set those or application id.
-    ::keymaster::AuthorizationSet swEnforced(::keymaster::AuthorizationSetBuilder().Authorization(
-            ::keymaster::TAG_CREATION_DATETIME, activeTimeMilliSeconds));
-
-    ::keymaster::AuthorizationSetBuilder hwEnforcedBuilder =
-            ::keymaster::AuthorizationSetBuilder()
-                    .Authorization(::keymaster::TAG_PURPOSE, KM_PURPOSE_SIGN)
-                    .Authorization(::keymaster::TAG_KEY_SIZE, 256)
-                    .Authorization(::keymaster::TAG_ALGORITHM, KM_ALGORITHM_EC)
-                    .Authorization(::keymaster::TAG_NO_AUTH_REQUIRED)
-                    .Authorization(::keymaster::TAG_DIGEST, KM_DIGEST_SHA_2_256)
-                    .Authorization(::keymaster::TAG_EC_CURVE, KM_EC_CURVE_P_256)
-                    .Authorization(::keymaster::TAG_OS_VERSION, 42)
-                    .Authorization(::keymaster::TAG_OS_PATCHLEVEL, 43);
-
-    // Only include TAG_IDENTITY_CREDENTIAL_KEY if it's not a test credential
-    if (!isTestCredential) {
-        hwEnforcedBuilder.Authorization(::keymaster::TAG_IDENTITY_CREDENTIAL_KEY);
+    optional<vector<vector<uint8_t>>> attestationCertChain = signAttestationCertificate(
+            context, pkey.get(), applicationId, challenge, attestationKeyBlob, *derIssuerSubject,
+            validFromMs, *notAfterMs, isTestCredential);
+    if (!attestationCertChain) {
+        LOG(ERROR) << "Error signing attestation certificate";
+        return std::nullopt;
     }
-    ::keymaster::AuthorizationSet hwEnforced(hwEnforcedBuilder);
-
-    ::keymaster::CertificateChain cert_chain_out = generate_attestation(
-            key, swEnforced, hwEnforced, auth_set, {} /* attest_key */, context, &error);
-
-    if (KM_ERROR_OK != error) {
-        LOG(ERROR) << "Error generating attestation from EVP key: " << error;
-        return {};
-    }
-
-    // translate certificate format from keymaster_cert_chain_t to vector<vector<uint8_t>>.
-    vector<vector<uint8_t>> attestationCertificate;
-    for (std::size_t i = 0; i < cert_chain_out.entry_count; i++) {
-        attestationCertificate.insert(
-                attestationCertificate.end(),
-                vector<uint8_t>(
-                        cert_chain_out.entries[i].data,
-                        cert_chain_out.entries[i].data + cert_chain_out.entries[i].data_length));
-    }
-
-    return attestationCertificate;
-}
-
-optional<std::pair<vector<uint8_t>, vector<vector<uint8_t>>>> createEcKeyPairAndAttestation(
-        const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId,
-        bool isTestCredential) {
-    auto ec_key = ::keymaster::EC_KEY_Ptr(EC_KEY_new());
-    auto pkey = ::keymaster::EVP_PKEY_Ptr(EVP_PKEY_new());
-    auto group = ::keymaster::EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
-
-    if (ec_key.get() == nullptr || pkey.get() == nullptr) {
-        LOG(ERROR) << "Memory allocation failed";
-        return {};
-    }
-
-    if (EC_KEY_set_group(ec_key.get(), group.get()) != 1 ||
-        EC_KEY_generate_key(ec_key.get()) != 1 || EC_KEY_check_key(ec_key.get()) < 0) {
-        LOG(ERROR) << "Error generating key";
-        return {};
-    }
-
-    if (EVP_PKEY_set1_EC_KEY(pkey.get(), ec_key.get()) != 1) {
-        LOG(ERROR) << "Error getting private key";
-        return {};
-    }
-
-    uint64_t nowMs = time(nullptr) * 1000;
-    uint64_t expireTimeMs = 0;  // Set to same as batch certificate
-
-    optional<vector<vector<uint8_t>>> attestationCert = createAttestation(
-            pkey.get(), applicationId, challenge, nowMs, expireTimeMs, isTestCredential);
-    if (!attestationCert) {
+    if (!attestationCertChain) {
         LOG(ERROR) << "Error create attestation from key and challenge";
-        return {};
+        return std::nullopt;
+    }
+    if (attestationCertChain->size() != 1) {
+        LOG(ERROR) << "Expected exactly one attestation cert, got " << attestationCertChain->size();
+        return std::nullopt;
     }
 
-    int size = i2d_PrivateKey(pkey.get(), nullptr);
-    if (size == 0) {
-        LOG(ERROR) << "Error generating public key encoding";
-        return {};
+    optional<vector<uint8_t>> keyPair = derEncodeKeyPair(*pkey);
+    if (!keyPair) {
+        return std::nullopt;
     }
 
-    vector<uint8_t> keyPair(size);
-    unsigned char* p = keyPair.data();
-    i2d_PrivateKey(pkey.get(), &p);
-
-    return make_pair(keyPair, attestationCert.value());
+    return make_pair(*keyPair, attestationCertChain->at(0));
 }
 
 optional<vector<vector<uint8_t>>> createAttestationForEcPublicKey(
@@ -820,12 +927,8 @@
         return {};
     }
 
-    uint64_t nowMs = time(nullptr) * 1000;
-    uint64_t expireTimeMs = 0;  // Set to same as batch certificate
-
     optional<vector<vector<uint8_t>>> attestationCert =
-            createAttestation(pkey.get(), applicationId, challenge, nowMs, expireTimeMs,
-                              false /* isTestCredential */);
+            createAttestation(pkey.get(), applicationId, challenge, false /* isTestCredential */);
     if (!attestationCert) {
         LOG(ERROR) << "Error create attestation from key and challenge";
         return {};
@@ -1134,6 +1237,14 @@
         return {};
     }
 
+    return ecPublicKeyGenerateCertificate(pkey.get(), privPkey.get(), serialDecimal, issuer,
+                                          subject, validityNotBefore, validityNotAfter, extensions);
+}
+
+optional<vector<uint8_t>> ecPublicKeyGenerateCertificate(
+        EVP_PKEY* publicKey, EVP_PKEY* signingKey, const string& serialDecimal,
+        const string& issuer, const string& subject, time_t validityNotBefore,
+        time_t validityNotAfter, const map<string, vector<uint8_t>>& extensions) {
     auto x509 = X509_Ptr(X509_new());
     if (!x509.get()) {
         LOG(ERROR) << "Error creating X509 certificate";
@@ -1145,7 +1256,7 @@
         return {};
     }
 
-    if (X509_set_pubkey(x509.get(), pkey.get()) != 1) {
+    if (X509_set_pubkey(x509.get(), publicKey) != 1) {
         LOG(ERROR) << "Error setting public key";
         return {};
     }
@@ -1220,7 +1331,7 @@
         }
     }
 
-    if (X509_sign(x509.get(), privPkey.get(), EVP_sha256()) == 0) {
+    if (X509_sign(x509.get(), signingKey, EVP_sha256()) == 0) {
         LOG(ERROR) << "Error signing X509 certificate";
         return {};
     }
@@ -2182,6 +2293,36 @@
     return testHardwareBoundKey;
 }
 
+optional<vector<uint8_t>> extractDerSubjectFromCertificate(const vector<uint8_t>& certificate) {
+    const uint8_t* input = certificate.data();
+    X509_Ptr cert(d2i_X509(/*cert=*/nullptr, &input, certificate.size()));
+    if (!cert) {
+        LOG(ERROR) << "Failed to parse certificate";
+        return std::nullopt;
+    }
+
+    X509_NAME* subject = X509_get_subject_name(cert.get());
+    if (!subject) {
+        LOG(ERROR) << "Failed to retrieve subject name";
+        return std::nullopt;
+    }
+
+    int encodedSubjectLength = i2d_X509_NAME(subject, /*out=*/nullptr);
+    if (encodedSubjectLength < 0) {
+        LOG(ERROR) << "Error obtaining encoded subject name length";
+        return std::nullopt;
+    }
+
+    vector<uint8_t> encodedSubject(encodedSubjectLength);
+    uint8_t* out = encodedSubject.data();
+    if (encodedSubjectLength != i2d_X509_NAME(subject, &out)) {
+        LOG(ERROR) << "Error encoding subject name";
+        return std::nullopt;
+    }
+
+    return encodedSubject;
+}
+
 }  // namespace support
 }  // namespace identity
 }  // namespace hardware
diff --git a/input/classifier/1.0/vts/functional/OWNERS b/input/classifier/1.0/vts/functional/OWNERS
new file mode 100644
index 0000000..540b75b
--- /dev/null
+++ b/input/classifier/1.0/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 136048
+svv@google.com
diff --git a/ir/OWNERS b/ir/OWNERS
new file mode 100644
index 0000000..04de9ef
--- /dev/null
+++ b/ir/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 163905
+connoro@google.com
diff --git a/ir/aidl/Android.bp b/ir/aidl/Android.bp
new file mode 100644
index 0000000..a623491
--- /dev/null
+++ b/ir/aidl/Android.bp
@@ -0,0 +1,43 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+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.ir",
+    vendor_available: true,
+    srcs: ["android/hardware/ir/*.aidl"],
+    stability: "vintf",
+    backend: {
+        cpp: {
+            enabled: false,
+        },
+        java: {
+            sdk_version: "module_current",
+        },
+        ndk: {
+            vndk: {
+                // TODO(b/206116595) enable this
+                enabled: false,
+            },
+        },
+    },
+}
diff --git a/ir/aidl/aidl_api/android.hardware.ir/current/android/hardware/ir/ConsumerIrFreqRange.aidl b/ir/aidl/aidl_api/android.hardware.ir/current/android/hardware/ir/ConsumerIrFreqRange.aidl
new file mode 100644
index 0000000..4a0d286
--- /dev/null
+++ b/ir/aidl/aidl_api/android.hardware.ir/current/android/hardware/ir/ConsumerIrFreqRange.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.ir;
+@VintfStability
+parcelable ConsumerIrFreqRange {
+  int minHz;
+  int maxHz;
+}
diff --git a/ir/aidl/aidl_api/android.hardware.ir/current/android/hardware/ir/IConsumerIr.aidl b/ir/aidl/aidl_api/android.hardware.ir/current/android/hardware/ir/IConsumerIr.aidl
new file mode 100644
index 0000000..07bf4b4
--- /dev/null
+++ b/ir/aidl/aidl_api/android.hardware.ir/current/android/hardware/ir/IConsumerIr.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.ir;
+@VintfStability
+interface IConsumerIr {
+  android.hardware.ir.ConsumerIrFreqRange[] getCarrierFreqs();
+  void transmit(in int carrierFreqHz, in int[] pattern);
+}
diff --git a/ir/aidl/android/hardware/ir/ConsumerIrFreqRange.aidl b/ir/aidl/android/hardware/ir/ConsumerIrFreqRange.aidl
new file mode 100644
index 0000000..ab0276a
--- /dev/null
+++ b/ir/aidl/android/hardware/ir/ConsumerIrFreqRange.aidl
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.ir;
+
+@VintfStability
+parcelable ConsumerIrFreqRange {
+    int minHz;
+    int maxHz;
+}
diff --git a/ir/aidl/android/hardware/ir/IConsumerIr.aidl b/ir/aidl/android/hardware/ir/IConsumerIr.aidl
new file mode 100644
index 0000000..f6f9742
--- /dev/null
+++ b/ir/aidl/android/hardware/ir/IConsumerIr.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.ir;
+
+import android.hardware.ir.ConsumerIrFreqRange;
+
+@VintfStability
+interface IConsumerIr {
+    /**
+     * Enumerates which frequencies the IR transmitter supports.
+     *
+     * @return - an array of all supported frequency ranges.
+     */
+    ConsumerIrFreqRange[] getCarrierFreqs();
+
+    /**
+     * Sends an IR pattern at a given frequency in HZ.
+     * This call must return when the transmit is complete or encounters an error.
+     *
+     * @param carrierFreq - Frequency of the transmission in HZ.
+     *
+     * @param pattern - Alternating series of on and off periods measured in
+     * microseconds. The carrier should be turned off at the end of a transmit
+     * even if there are an odd number of entries in the pattern array.
+     *
+     * @throws EX_UNSUPPORTED_OPERATION when the frequency is not supported.
+     */
+    void transmit(in int carrierFreqHz, in int[] pattern);
+}
diff --git a/ir/aidl/default/Android.bp b/ir/aidl/default/Android.bp
new file mode 100644
index 0000000..a4fb439
--- /dev/null
+++ b/ir/aidl/default/Android.bp
@@ -0,0 +1,42 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Example binder service of the ir HAL.
+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.ir-service.example",
+    relative_install_path: "hw",
+    init_rc: ["android.hardware.ir-service.example.rc"],
+    vendor: true,
+    vintf_fragments: ["android.hardware.ir-service.example.xml"],
+
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "libcutils",
+        "liblog",
+        "libutils",
+        "android.hardware.ir-V1-ndk",
+    ],
+
+    srcs: ["main.cpp"],
+}
diff --git a/ir/aidl/default/android.hardware.ir-service.example.rc b/ir/aidl/default/android.hardware.ir-service.example.rc
new file mode 100644
index 0000000..56def64
--- /dev/null
+++ b/ir/aidl/default/android.hardware.ir-service.example.rc
@@ -0,0 +1,4 @@
+service vendor.ir-default /vendor/bin/hw/android.hardware.ir-service.example
+    class hal
+    user nobody
+    group nobody
diff --git a/ir/aidl/default/android.hardware.ir-service.example.xml b/ir/aidl/default/android.hardware.ir-service.example.xml
new file mode 100644
index 0000000..1a63520
--- /dev/null
+++ b/ir/aidl/default/android.hardware.ir-service.example.xml
@@ -0,0 +1,7 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.ir</name>
+        <version>1</version>
+        <fqname>IConsumerIr/default</fqname>
+    </hal>
+</manifest>
diff --git a/ir/aidl/default/main.cpp b/ir/aidl/default/main.cpp
new file mode 100644
index 0000000..7c4a816
--- /dev/null
+++ b/ir/aidl/default/main.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aidl/android/hardware/ir/BnConsumerIr.h>
+#include <android-base/logging.h>
+#include <android/binder_interface_utils.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <numeric>
+
+namespace aidl::android::hardware::ir {
+
+const std::vector<ConsumerIrFreqRange> kSupportedFreqs = {
+        {2000, 4000},
+        {10000, 30000},
+};
+
+class ConsumerIr : public BnConsumerIr {
+    ::ndk::ScopedAStatus getCarrierFreqs(std::vector<ConsumerIrFreqRange>* _aidl_return) override;
+    ::ndk::ScopedAStatus transmit(int32_t in_carrierFreqHz,
+                                  const std::vector<int32_t>& in_pattern) override;
+};
+
+::ndk::ScopedAStatus ConsumerIr::getCarrierFreqs(std::vector<ConsumerIrFreqRange>* _aidl_return) {
+    *_aidl_return = kSupportedFreqs;
+    return ::ndk::ScopedAStatus::ok();
+}
+
+bool isSupportedFreq(int32_t freq) {
+    for (const auto& range : kSupportedFreqs) {
+        if (freq >= range.minHz && freq <= range.maxHz) return true;
+    }
+    return false;
+}
+
+::ndk::ScopedAStatus ConsumerIr::transmit(int32_t in_carrierFreqHz,
+                                          const std::vector<int32_t>& in_pattern) {
+    if (isSupportedFreq(in_carrierFreqHz)) {
+        // trasmit the pattern, each integer is number of microseconds in an
+        // alternating on/off state.
+        usleep(std::accumulate(in_pattern.begin(), in_pattern.end(), 0));
+        return ::ndk::ScopedAStatus::ok();
+    } else {
+        // unsupported operation
+        return ::ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+    }
+    return ::ndk::ScopedAStatus::ok();
+}
+
+}  // namespace aidl::android::hardware::ir
+
+using aidl::android::hardware::ir::ConsumerIr;
+
+int main() {
+    auto binder = ::ndk::SharedRefBase::make<ConsumerIr>();
+    const std::string name = std::string() + ConsumerIr::descriptor + "/default";
+    CHECK_EQ(STATUS_OK, AServiceManager_addService(binder->asBinder().get(), name.c_str()))
+            << "Failed to register " << name;
+
+    ABinderProcess_setThreadPoolMaxThreadCount(0);
+    ABinderProcess_joinThreadPool();
+
+    return EXIT_FAILURE;  // should not reached
+}
diff --git a/ir/aidl/vts/Android.bp b/ir/aidl/vts/Android.bp
new file mode 100644
index 0000000..c2491b8
--- /dev/null
+++ b/ir/aidl/vts/Android.bp
@@ -0,0 +1,43 @@
+//
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+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: "VtsHalIrTargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    srcs: ["VtsHalIrTargetTest.cpp"],
+    shared_libs: [
+        "libbinder_ndk",
+    ],
+    static_libs: [
+        "android.hardware.ir-V1-ndk",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
diff --git a/ir/aidl/vts/VtsHalIrTargetTest.cpp b/ir/aidl/vts/VtsHalIrTargetTest.cpp
new file mode 100644
index 0000000..3527625
--- /dev/null
+++ b/ir/aidl/vts/VtsHalIrTargetTest.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "ir_aidl_hal_test"
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/ir/IConsumerIr.h>
+#include <android-base/logging.h>
+#include <android/binder_auto_utils.h>
+#include <android/binder_manager.h>
+#include <gtest/gtest.h>
+#include <algorithm>
+#include <vector>
+
+using ::aidl::android::hardware::ir::ConsumerIrFreqRange;
+using ::aidl::android::hardware::ir::IConsumerIr;
+using ::ndk::SpAIBinder;
+
+class ConsumerIrTest : public ::testing::TestWithParam<std::string> {
+  public:
+    virtual void SetUp() override {
+        mIr = IConsumerIr::fromBinder(
+                SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+        ASSERT_NE(mIr, nullptr);
+    }
+
+    std::shared_ptr<IConsumerIr> mIr;
+};
+
+// Test transmit() for the min and max frequency of every available range
+TEST_P(ConsumerIrTest, TransmitTest) {
+    std::vector<ConsumerIrFreqRange> ranges;
+    const auto& ret = mIr->getCarrierFreqs(&ranges);
+    ASSERT_TRUE(ret.isOk());
+
+    if (ranges.size() > 0) {
+        uint32_t len = 16;
+        std::vector<int32_t> vec;
+        vec.resize(len);
+        std::fill(vec.begin(), vec.end(), 1000);
+        for (auto range = ranges.begin(); range != ranges.end(); range++) {
+            EXPECT_TRUE(mIr->transmit(range->minHz, vec).isOk());
+            EXPECT_TRUE(mIr->transmit(range->maxHz, vec).isOk());
+        }
+    }
+}
+
+// Test transmit() when called with invalid frequencies
+TEST_P(ConsumerIrTest, BadFreqTest) {
+    uint32_t len = 16;
+    std::vector<int32_t> vec;
+    vec.resize(len);
+    std::fill(vec.begin(), vec.end(), 1);
+    const auto& res = mIr->transmit(-1, vec);
+    EXPECT_FALSE(res.isOk());
+    EXPECT_EQ(res.getExceptionCode(), EX_UNSUPPORTED_OPERATION);
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ConsumerIrTest);
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, ConsumerIrTest,
+        testing::ValuesIn(android::getAidlHalInstanceNames(IConsumerIr::descriptor)),
+        ::android::PrintInstanceNameToString);
diff --git a/keymaster/3.0/vts/OWNERS b/keymaster/3.0/vts/OWNERS
index 376c12b..846bb84 100644
--- a/keymaster/3.0/vts/OWNERS
+++ b/keymaster/3.0/vts/OWNERS
@@ -1,3 +1,4 @@
+drysdale@google.com
 jdanis@google.com
 swillden@google.com
 yim@google.com
diff --git a/keymaster/3.0/vts/functional/Android.bp b/keymaster/3.0/vts/functional/Android.bp
index e2ae803..fde32a7 100644
--- a/keymaster/3.0/vts/functional/Android.bp
+++ b/keymaster/3.0/vts/functional/Android.bp
@@ -26,6 +26,9 @@
 cc_test {
     name: "VtsHalKeymasterV3_0TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: [
+        "keymaster_hidl_hal_test.cpp",
+    ],
     srcs: [
         "authorization_set.cpp",
         "attestation_record.cpp",
@@ -38,5 +41,11 @@
         "libcrypto_static",
         "libsoftkeymasterdevice",
     ],
-    test_suites: ["general-tests", "vts"],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+    sanitize: {
+        cfi: false,
+    },
 }
diff --git a/keymaster/3.0/vts/functional/OWNERS b/keymaster/3.0/vts/functional/OWNERS
new file mode 100644
index 0000000..2ef9086
--- /dev/null
+++ b/keymaster/3.0/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 189335
+swillden@google.com
diff --git a/keymaster/4.0/IKeymasterDevice.hal b/keymaster/4.0/IKeymasterDevice.hal
index dfde060..1c6ae47 100644
--- a/keymaster/4.0/IKeymasterDevice.hal
+++ b/keymaster/4.0/IKeymasterDevice.hal
@@ -1254,7 +1254,8 @@
      * o PaddingMode::RSA_PSS.  For PSS-padded signature operations, the PSS salt length must match
      *   the size of the PSS digest selected.  The digest specified with Tag::DIGEST in inputParams
      *   on begin() must be used as the PSS digest algorithm, MGF1 must be used as the mask
-     *   generation function and SHA1 must be used as the MGF1 digest algorithm.
+     *   generation function and the digest specified with Tag:DIGEST in inputParams must also be
+     *   used as the MGF1 digest algorithm.
      *
      * o PaddingMode::RSA_OAEP.  The digest specified with Tag::DIGEST in inputParams on begin is
      *   used as the OAEP digest algorithm, MGF1 must be used as the mask generation function and
diff --git a/keymaster/4.0/support/fuzzer/Android.bp b/keymaster/4.0/support/fuzzer/Android.bp
new file mode 100644
index 0000000..8bc681a
--- /dev/null
+++ b/keymaster/4.0/support/fuzzer/Android.bp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+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: "keymaster4_fuzzer_defaults",
+    static_libs: [
+        "libbase",
+        "liblog",
+        "libkeymaster4support",
+    ],
+    shared_libs: [
+        "android.hardware.keymaster@4.0",
+        "libcrypto",
+        "libhidlbase",
+        "libutils",
+    ],
+    fuzz_config: {
+        cc: [
+            "android-media-fuzzing-reports@google.com",
+        ],
+        componentid: 533764,
+    },
+}
+
+cc_fuzz {
+    name: "keymaster4_attestation_fuzzer",
+    defaults: [
+        "keymaster4_fuzzer_defaults",
+    ],
+    srcs: [
+        "keymaster4_attestation_fuzzer.cpp",
+    ],
+}
+
+cc_fuzz {
+    name: "keymaster4_authSet_fuzzer",
+    defaults: [
+        "keymaster4_fuzzer_defaults",
+    ],
+    srcs: [
+        "keymaster4_authSet_fuzzer.cpp",
+    ],
+}
+
+cc_fuzz {
+    name: "keymaster4_utils_fuzzer",
+    defaults: [
+        "keymaster4_fuzzer_defaults",
+    ],
+    srcs: [
+        "keymaster4_utils_fuzzer.cpp",
+    ],
+}
diff --git a/keymaster/4.0/support/fuzzer/README.md b/keymaster/4.0/support/fuzzer/README.md
new file mode 100644
index 0000000..bf4af25
--- /dev/null
+++ b/keymaster/4.0/support/fuzzer/README.md
@@ -0,0 +1,58 @@
+# Fuzzers for libkeymaster4support
+
+## Plugin Design Considerations
+The fuzzer plugins for libkeymaster4support are designed based on the understanding of the
+source code and try to achieve the following:
+
+##### Maximize code coverage
+The configuration parameters are not hardcoded, but instead selected based on
+incoming data. This ensures more code paths are reached by the fuzzers.
+
+libkeymaster4support supports the following parameters:
+1. Security Level (parameter name: `securityLevel`)
+2. Ec Curve (parameter name: `ecCurve`)
+3. Padding Mode (parameter name: `paddingMode`)
+4. Digest (parameter name: `digest`)
+5. Tag (parameter name: `tag`)
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+| `securityLevel` | 0.`SecurityLevel::SOFTWARE` 1.`SecurityLevel::TRUSTED_ENVIRONMENT` 2.`SecurityLevel::STRONGBOX`| Value obtained from FuzzedDataProvider|
+| `ecCurve` | 0.`EcCurve::P_224` 1.`EcCurve::P_256` 2.`EcCurve::P_384` 3. `EcCurve::P_521`| Value obtained from FuzzedDataProvider|
+| `paddingMode` | 0.`PaddingMode::NONE` 1.`PaddingMode::RSA_OAEP` 2.`PaddingMode::RSA_PSS` 3. `PaddingMode::RSA_PKCS1_1_5_ENCRYPT` 4.`PaddingMode::RSA_PKCS1_1_5_SIGN` 5.`PaddingMode::PKCS7`| Value obtained from FuzzedDataProvider|
+| `digest` | 1. `Digest::NONE` 2.`Digest::MD5` 3.`Digest::SHA1` 4.`Digest::SHA_2_224` 5.`Digest::SHA_2_256` 6.`Digest::SHA_2_384`  7.`Digest::SHA_2_512`| Value obtained from FuzzedDataProvider|
+| `tag` | 1. `Tag::INVALID` 2.`Tag::PURPOSE` 3.`Tag::ALGORITHM` 4.`Tag::KEY_SIZE` 5.`Tag::BLOCK_MODE` 6.`Tag::DIGEST` 7.`Tag::PADDING` 8.`Tag::CALLER_NONCE` 9.`Tag::MIN_MAC_LENGTH` 10.`Tag::EC_CURVE` 11.`Tag::RSA_PUBLIC_EXPONENT` 12.`Tag::INCLUDE_UNIQUE_ID` 13. `Tag::BLOB_USAGE_REQUIREMENTS` 14.`Tag::BOOTLOADER_ONLY` 15.`Tag::ROLLBACK_RESISTANCE` 16.`Tag::HARDWARE_TYPE` 17.`Tag::ACTIVE_DATETIME` 18. `Tag::ORIGINATION_EXPIRE_DATETIME` 19.`Tag::USAGE_EXPIRE_DATETIME` 20.`Tag::MIN_SECONDS_BETWEEN_OPS` 21.`Tag::MAX_USES_PER_BOOT` 22.`Tag::USER_ID` 23.` Tag::USER_SECURE_ID` 24.`Tag::NO_AUTH_REQUIRED` 25.`Tag::USER_AUTH_TYPE` 26.`Tag::AUTH_TIMEOUT` 27.`Tag::ALLOW_WHILE_ON_BODY` 28.`Tag::TRUSTED_USER_PRESENCE_REQUIRED` 29.`Tag::TRUSTED_CONFIRMATION_REQUIRED` 30.`Tag::UNLOCKED_DEVICE_REQUIRED` 31.`Tag::APPLICATION_ID` 32.`Tag::APPLICATION_DATA` 33.`Tag::CREATION_DATETIME` 34.`Tag::ORIGIN` 35.`Tag::ROOT_OF_TRUST` 36.`Tag::OS_VERSION` 37.`Tag::OS_PATCHLEVEL` 38.`Tag::UNIQUE_ID` 39.`Tag::ATTESTATION_CHALLENGE` 40.`Tag::ATTESTATION_APPLICATION_ID` 41.`Tag::ATTESTATION_ID_BRAND` 42.`Tag::ATTESTATION_ID_DEVICE` 43.`Tag::ATTESTATION_ID_PRODUCT` 44.`Tag::ATTESTATION_ID_SERIAL` 45.`Tag::ATTESTATION_ID_IMEI` 46.`Tag::ATTESTATION_ID_MEID` 47.`Tag::ATTESTATION_ID_MANUFACTURER` 48.`Tag::ATTESTATION_ID_MODEL` 49.`Tag::VENDOR_PATCHLEVEL` 50.`Tag::BOOT_PATCHLEVEL` 51.`Tag::ASSOCIATED_DATA` 52.`Tag::NONCE` 53.`Tag::MAC_LENGTH` 54.`Tag::RESET_SINCE_ID_ROTATION` 55.`Tag::CONFIRMATION_TOKEN`| Value obtained from FuzzedDataProvider|
+
+This also ensures that the plugins are always deterministic for any given input.
+
+##### Maximize utilization of input data
+The plugins feed the entire input data to the module.
+This ensures that the plugins tolerate any kind of input (empty, huge,
+malformed, etc) and dont `exit()` on any input and thereby increasing the
+chance of identifying vulnerabilities.
+
+## Build
+
+This describes steps to build keymaster4_attestation_fuzzer, keymaster4_authSet_fuzzer and keymaster4_utils_fuzzer binaries
+
+### Android
+
+#### Steps to build
+Build the fuzzer
+```
+  $ mm -j$(nproc) keymaster4_attestation_fuzzer
+  $ mm -j$(nproc) keymaster4_authSet_fuzzer
+  $ mm -j$(nproc) keymaster4_utils_fuzzer
+```
+#### Steps to run
+To run on device
+```
+  $ adb sync data
+  $ adb shell /data/fuzz/${TARGET_ARCH}/keymaster4_attestation_fuzzer/keymaster4_attestation_fuzzer
+  $ adb shell /data/fuzz/${TARGET_ARCH}/keymaster4_authSet_fuzzer/keymaster4_authSet_fuzzer
+  $ adb shell /data/fuzz/${TARGET_ARCH}/keymaster4_utils_fuzzer/keymaster4_utils_fuzzer
+```
+
+## References:
+ * http://llvm.org/docs/LibFuzzer.html
+ * https://github.com/google/oss-fuzz
diff --git a/keymaster/4.0/support/fuzzer/keymaster4_attestation_fuzzer.cpp b/keymaster/4.0/support/fuzzer/keymaster4_attestation_fuzzer.cpp
new file mode 100644
index 0000000..b8b858d
--- /dev/null
+++ b/keymaster/4.0/support/fuzzer/keymaster4_attestation_fuzzer.cpp
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include <android/hardware/keymaster/4.0/IKeymasterDevice.h>
+#include <keymasterV4_0/attestation_record.h>
+#include <keymasterV4_0/openssl_utils.h>
+#include "keymaster4_common.h"
+
+namespace android::hardware::keymaster::V4_0::fuzzer {
+
+constexpr size_t kMinBytes = 1;
+constexpr size_t kMaxBytes = 10;
+
+class KeyMaster4AttestationFuzzer {
+  public:
+    void process(const uint8_t* data, size_t size);
+
+  private:
+    ErrorCode generateKey(const AuthorizationSet& keyDesc, hidl_vec<uint8_t>* keyBlob,
+                          KeyCharacteristics* keyCharacteristics);
+    ErrorCode attestKey(hidl_vec<uint8_t>& keyBlob, const AuthorizationSet& attestParams,
+                        hidl_vec<hidl_vec<uint8_t>>* certificateChain);
+    X509_Ptr parseCertificateBlob(const hidl_vec<uint8_t>& blob);
+    ASN1_OCTET_STRING* getAttestationRecord(const X509* certificate);
+    bool verifyAttestationRecord(const hidl_vec<uint8_t>& attestationCert);
+    void invokeAttestationRecord();
+
+    sp<IKeymasterDevice> mKeymaster = nullptr;
+    std::unique_ptr<FuzzedDataProvider> mFdp = nullptr;
+};
+
+ErrorCode KeyMaster4AttestationFuzzer::generateKey(const AuthorizationSet& key_desc,
+                                                   hidl_vec<uint8_t>* keyBlob,
+                                                   KeyCharacteristics* keyCharacteristics) {
+    ErrorCode error;
+    mKeymaster->generateKey(key_desc.hidl_data(),
+                            [&](ErrorCode hidlError, const hidl_vec<uint8_t>& hidlKeyBlob,
+                                const KeyCharacteristics& hidlKeyCharacteristics) {
+                                error = hidlError;
+                                *keyBlob = hidlKeyBlob;
+                                *keyCharacteristics = hidlKeyCharacteristics;
+                            });
+    return error;
+}
+
+ErrorCode KeyMaster4AttestationFuzzer::attestKey(hidl_vec<uint8_t>& keyBlob,
+                                                 const AuthorizationSet& attestParams,
+                                                 hidl_vec<hidl_vec<uint8_t>>* certificateChain) {
+    ErrorCode error;
+    auto rc = mKeymaster->attestKey(
+            keyBlob, attestParams.hidl_data(),
+            [&](ErrorCode hidlError, const hidl_vec<hidl_vec<uint8_t>>& hidlCertificateChain) {
+                error = hidlError;
+                *certificateChain = hidlCertificateChain;
+            });
+
+    if (!rc.isOk()) {
+        return ErrorCode::UNKNOWN_ERROR;
+    }
+    return error;
+}
+
+X509_Ptr KeyMaster4AttestationFuzzer::parseCertificateBlob(const hidl_vec<uint8_t>& blob) {
+    const uint8_t* p = blob.data();
+    return X509_Ptr(d2i_X509(nullptr, &p, blob.size()));
+}
+
+/**
+ * @brief getAttestationRecord() accepts a 'certificate' pointer and the return value points to the
+ * data owned by 'certificate'. Hence, 'certificate' should not be freed and the return value cannot
+ * outlive 'certificate'
+ */
+ASN1_OCTET_STRING* KeyMaster4AttestationFuzzer::getAttestationRecord(const X509* certificate) {
+    ASN1_OBJECT_Ptr oid(OBJ_txt2obj(kAttestionRecordOid, 1 /* dotted string format */));
+    if (!oid.get()) {
+        return nullptr;
+    }
+
+    int location = X509_get_ext_by_OBJ(certificate, oid.get(), -1 /* search from beginning */);
+    if (location == -1) {
+        return nullptr;
+    }
+
+    X509_EXTENSION* attestRecordExt = X509_get_ext(certificate, location);
+    if (!attestRecordExt) {
+        return nullptr;
+    }
+
+    ASN1_OCTET_STRING* attestRecord = X509_EXTENSION_get_data(attestRecordExt);
+    return attestRecord;
+}
+
+bool KeyMaster4AttestationFuzzer::verifyAttestationRecord(
+        const hidl_vec<uint8_t>& attestationCert) {
+    X509_Ptr cert(parseCertificateBlob(attestationCert));
+    if (!cert.get()) {
+        return false;
+    }
+
+    ASN1_OCTET_STRING* attestRecord = getAttestationRecord(cert.get());
+    if (!attestRecord) {
+        return false;
+    }
+
+    AuthorizationSet attestationSwEnforced;
+    AuthorizationSet attestationHwEnforced;
+    uint32_t attestationVersion;
+    uint32_t keymasterVersion;
+    SecurityLevel securityLevel;
+    SecurityLevel keymasterSecurityLevel;
+    hidl_vec<uint8_t> attestationChallenge;
+    hidl_vec<uint8_t> attestationUniqueId;
+
+    auto error = parse_attestation_record(
+            attestRecord->data, attestRecord->length, &attestationVersion, &securityLevel,
+            &keymasterVersion, &keymasterSecurityLevel, &attestationChallenge,
+            &attestationSwEnforced, &attestationHwEnforced, &attestationUniqueId);
+    if (error != ErrorCode::OK) {
+        return false;
+    }
+
+    hidl_vec<uint8_t> verifiedBootKey;
+    keymaster_verified_boot_t verifiedBootState;
+    bool device_locked;
+    hidl_vec<uint8_t> verifiedBootHash;
+
+    parse_root_of_trust(attestRecord->data, attestRecord->length, &verifiedBootKey,
+                        &verifiedBootState, &device_locked, &verifiedBootHash);
+    return true;
+}
+
+void KeyMaster4AttestationFuzzer::invokeAttestationRecord() {
+    mKeymaster = IKeymasterDevice::getService();
+    if (!mKeymaster) {
+        return;
+    }
+
+    hidl_vec<uint8_t> keyBlob;
+    KeyCharacteristics keyCharacteristics;
+    generateKey(createAuthorizationSet(mFdp), &keyBlob, &keyCharacteristics);
+
+    hidl_vec<hidl_vec<uint8_t>> certificateChain;
+
+    std::vector<uint8_t> challenge, attestationId;
+    challenge =
+            mFdp->ConsumeBytes<uint8_t>(mFdp->ConsumeIntegralInRange<size_t>(kMinBytes, kMaxBytes));
+    attestationId =
+            mFdp->ConsumeBytes<uint8_t>(mFdp->ConsumeIntegralInRange<size_t>(kMinBytes, kMaxBytes));
+    attestKey(keyBlob,
+              AuthorizationSetBuilder()
+                      .Authorization(TAG_ATTESTATION_CHALLENGE, challenge)
+                      .Authorization(TAG_ATTESTATION_APPLICATION_ID, attestationId),
+              &certificateChain);
+
+    if (certificateChain.size() > 0) {
+        verifyAttestationRecord(certificateChain[mFdp->ConsumeIntegralInRange<size_t>(
+                0, certificateChain.size() - 1)]);
+    }
+}
+
+void KeyMaster4AttestationFuzzer::process(const uint8_t* data, size_t size) {
+    mFdp = std::make_unique<FuzzedDataProvider>(data, size);
+    invokeAttestationRecord();
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    KeyMaster4AttestationFuzzer km4AttestationFuzzer;
+    km4AttestationFuzzer.process(data, size);
+    return 0;
+}
+
+}  // namespace android::hardware::keymaster::V4_0::fuzzer
diff --git a/keymaster/4.0/support/fuzzer/keymaster4_authSet_fuzzer.cpp b/keymaster/4.0/support/fuzzer/keymaster4_authSet_fuzzer.cpp
new file mode 100644
index 0000000..63e0499
--- /dev/null
+++ b/keymaster/4.0/support/fuzzer/keymaster4_authSet_fuzzer.cpp
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include <fstream>
+#include "keymaster4_common.h"
+
+namespace android::hardware::keymaster::V4_0::fuzzer {
+
+constexpr size_t kMaxVectorSize = 100;
+constexpr size_t kMaxKeyParameter = 10;
+
+constexpr Tag kTagArray[] = {Tag::INVALID,
+                             Tag::PURPOSE,
+                             Tag::ALGORITHM,
+                             Tag::KEY_SIZE,
+                             Tag::BLOCK_MODE,
+                             Tag::DIGEST,
+                             Tag::PADDING,
+                             Tag::CALLER_NONCE,
+                             Tag::MIN_MAC_LENGTH,
+                             Tag::EC_CURVE,
+                             Tag::RSA_PUBLIC_EXPONENT,
+                             Tag::INCLUDE_UNIQUE_ID,
+                             Tag::BLOB_USAGE_REQUIREMENTS,
+                             Tag::BOOTLOADER_ONLY,
+                             Tag::ROLLBACK_RESISTANCE,
+                             Tag::HARDWARE_TYPE,
+                             Tag::ACTIVE_DATETIME,
+                             Tag::ORIGINATION_EXPIRE_DATETIME,
+                             Tag::USAGE_EXPIRE_DATETIME,
+                             Tag::MIN_SECONDS_BETWEEN_OPS,
+                             Tag::MAX_USES_PER_BOOT,
+                             Tag::USER_ID,
+                             Tag::USER_SECURE_ID,
+                             Tag::NO_AUTH_REQUIRED,
+                             Tag::USER_AUTH_TYPE,
+                             Tag::AUTH_TIMEOUT,
+                             Tag::ALLOW_WHILE_ON_BODY,
+                             Tag::TRUSTED_USER_PRESENCE_REQUIRED,
+                             Tag::TRUSTED_CONFIRMATION_REQUIRED,
+                             Tag::UNLOCKED_DEVICE_REQUIRED,
+                             Tag::APPLICATION_ID,
+                             Tag::APPLICATION_DATA,
+                             Tag::CREATION_DATETIME,
+                             Tag::ORIGIN,
+                             Tag::ROOT_OF_TRUST,
+                             Tag::OS_VERSION,
+                             Tag::OS_PATCHLEVEL,
+                             Tag::UNIQUE_ID,
+                             Tag::ATTESTATION_CHALLENGE,
+                             Tag::ATTESTATION_APPLICATION_ID,
+                             Tag::ATTESTATION_ID_BRAND,
+                             Tag::ATTESTATION_ID_DEVICE,
+                             Tag::ATTESTATION_ID_PRODUCT,
+                             Tag::ATTESTATION_ID_SERIAL,
+                             Tag::ATTESTATION_ID_IMEI,
+                             Tag::ATTESTATION_ID_MEID,
+                             Tag::ATTESTATION_ID_MANUFACTURER,
+                             Tag::ATTESTATION_ID_MODEL,
+                             Tag::VENDOR_PATCHLEVEL,
+                             Tag::BOOT_PATCHLEVEL,
+                             Tag::ASSOCIATED_DATA,
+                             Tag::NONCE,
+                             Tag::MAC_LENGTH,
+                             Tag::RESET_SINCE_ID_ROTATION,
+                             Tag::CONFIRMATION_TOKEN};
+
+class KeyMaster4AuthSetFuzzer {
+  public:
+    void process(const uint8_t* data, size_t size);
+
+  private:
+    void invokeAuthSetAPIs();
+    std::unique_ptr<FuzzedDataProvider> mFdp = nullptr;
+};
+
+/**
+ * @brief invokeAuthSetAPIs() function aims at calling functions of authorization_set.cpp
+ * and authorization_set.h in order to get a good coverage for libkeymaster4support.
+ */
+void KeyMaster4AuthSetFuzzer::invokeAuthSetAPIs() {
+    AuthorizationSet authSet = createAuthorizationSet(mFdp);
+    while (mFdp->remaining_bytes() > 0) {
+        uint32_t action = mFdp->ConsumeIntegralInRange<uint32_t>(0, 15);
+        switch (action) {
+            case 0: {
+                authSet.Sort();
+            } break;
+            case 1: {
+                authSet.Deduplicate();
+            } break;
+            case 2: {
+                authSet.Union(createAuthorizationSet(mFdp));
+            } break;
+            case 3: {
+                authSet.Subtract(createAuthorizationSet(mFdp));
+            } break;
+            case 4: {
+                std::filebuf fbOut;
+                fbOut.open("/dev/zero", std::ios::out);
+                std::ostream out(&fbOut);
+                authSet.Serialize(&out);
+            } break;
+            case 5: {
+                std::filebuf fbIn;
+                fbIn.open("/dev/zero", std::ios::in);
+                std::istream in(&fbIn);
+                authSet.Deserialize(&in);
+            } break;
+            case 6: {  // invoke push_back()
+                AuthorizationSetBuilder builder = AuthorizationSetBuilder();
+                for (const KeyParameter& tag : authSet) {
+                    builder.push_back(tag);
+                }
+                AuthorizationSet params = createAuthorizationSet(mFdp);
+                authSet.push_back(params);
+            } break;
+            case 7: {  // invoke copy constructor
+                auto params = AuthorizationSetBuilder().Authorizations(authSet);
+                authSet = params;
+            } break;
+            case 8: {  // invoke move constructor
+                auto params = AuthorizationSetBuilder().Authorizations(authSet);
+                authSet = std::move(params);
+            } break;
+            case 9: {  // invoke Constructor from hidl_vec<KeyParameter>
+                hidl_vec<KeyParameter> keyParam;
+                size_t numKeyParam = mFdp->ConsumeIntegralInRange<size_t>(1, kMaxKeyParameter);
+                keyParam.resize(numKeyParam);
+                for (size_t i = 0; i < numKeyParam - 1; ++i) {
+                    keyParam[i].tag = mFdp->PickValueInArray(kTagArray);
+                    std::vector<uint8_t> dataVector = mFdp->ConsumeBytes<uint8_t>(
+                            mFdp->ConsumeIntegralInRange<size_t>(0, kMaxVectorSize));
+                    keyParam[i].blob = dataVector;
+                }
+                if (mFdp->ConsumeBool()) {
+                    AuthorizationSet auths(keyParam);
+                    auths.push_back(AuthorizationSet(keyParam));
+                } else {  // invoke operator=
+                    AuthorizationSet auths = keyParam;
+                }
+            } break;
+            case 10: {  // invoke 'Contains()'
+                Tag tag;
+                if (authSet.size() > 0) {
+                    tag = authSet[mFdp->ConsumeIntegralInRange<size_t>(0, authSet.size() - 1)].tag;
+                }
+                authSet.Contains(mFdp->ConsumeBool() ? tag : mFdp->PickValueInArray(kTagArray));
+            } break;
+            case 11: {  // invoke 'GetTagCount()'
+                Tag tag;
+                if (authSet.size() > 0) {
+                    tag = authSet[mFdp->ConsumeIntegralInRange<size_t>(0, authSet.size() - 1)].tag;
+                }
+                authSet.GetTagCount(mFdp->ConsumeBool() ? tag : mFdp->PickValueInArray(kTagArray));
+            } break;
+            case 12: {  // invoke 'empty()'
+                authSet.empty();
+            } break;
+            case 13: {  // invoke 'data()'
+                authSet.data();
+            } break;
+            case 14: {  // invoke 'hidl_data()'
+                authSet.hidl_data();
+            } break;
+            case 15: {  // invoke 'erase()'
+                if (authSet.size() > 0) {
+                    authSet.erase(mFdp->ConsumeIntegralInRange<size_t>(0, authSet.size() - 1));
+                }
+            } break;
+            default:
+                break;
+        };
+    }
+    authSet.Clear();
+}
+
+void KeyMaster4AuthSetFuzzer::process(const uint8_t* data, size_t size) {
+    mFdp = std::make_unique<FuzzedDataProvider>(data, size);
+    invokeAuthSetAPIs();
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    KeyMaster4AuthSetFuzzer km4AuthSetFuzzer;
+    km4AuthSetFuzzer.process(data, size);
+    return 0;
+}
+
+}  // namespace android::hardware::keymaster::V4_0::fuzzer
diff --git a/keymaster/4.0/support/fuzzer/keymaster4_common.h b/keymaster/4.0/support/fuzzer/keymaster4_common.h
new file mode 100644
index 0000000..f6e53ee
--- /dev/null
+++ b/keymaster/4.0/support/fuzzer/keymaster4_common.h
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#ifndef __KEYMASTER4_COMMON_H__
+#define __KEYMASTER4_COMMON_H__
+
+#include <fuzzer/FuzzedDataProvider.h>
+#include <keymasterV4_0/authorization_set.h>
+
+namespace android::hardware::keymaster::V4_0::fuzzer {
+
+using ::android::hardware::hidl_vec;
+
+constexpr uint32_t kKeySize = 2048;
+constexpr uint32_t kPublicExponent = 65537;
+
+constexpr EcCurve kCurve[] = {EcCurve::P_224, EcCurve::P_256, EcCurve::P_384, EcCurve::P_521};
+
+constexpr PaddingMode kPaddingMode[] = {
+        PaddingMode::NONE,
+        PaddingMode::RSA_OAEP,
+        PaddingMode::RSA_PSS,
+        PaddingMode::RSA_PKCS1_1_5_ENCRYPT,
+        PaddingMode::RSA_PKCS1_1_5_SIGN,
+        PaddingMode::PKCS7,
+};
+
+constexpr Digest kDigest[] = {
+        Digest::NONE,      Digest::MD5,       Digest::SHA1,      Digest::SHA_2_224,
+        Digest::SHA_2_256, Digest::SHA_2_384, Digest::SHA_2_512,
+};
+
+enum AuthSet : uint32_t {
+    RSA_SIGNING_KEY = 0u,
+    RSA_ENCRYPRION_KEY,
+    ECDSA_SIGNING_CURVE,
+    ECDSA_SIGNING_KEY,
+    AES_ENCRYPTION_KEY,
+    TRIPLE_DES,
+    HMAC,
+    NO_DIGEST,
+    ECB_MODE,
+    GSM_MODE_MIN_MAC,
+    GSM_MODE_MAC,
+    BLOCK_MODE,
+    kMaxValue = BLOCK_MODE
+};
+
+AuthorizationSet createAuthorizationSet(std::unique_ptr<FuzzedDataProvider>& dataProvider) {
+    uint32_t authSet = dataProvider->ConsumeEnum<AuthSet>();
+    switch (authSet) {
+        case RSA_SIGNING_KEY: {
+            Digest digest = dataProvider->PickValueInArray(kDigest);
+            PaddingMode padding = dataProvider->PickValueInArray(kPaddingMode);
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .RsaSigningKey(kKeySize, kPublicExponent)
+                    .Digest(digest)
+                    .Padding(padding)
+                    .Authorization(TAG_INCLUDE_UNIQUE_ID);
+        } break;
+        case RSA_ENCRYPRION_KEY: {
+            Digest digest = dataProvider->PickValueInArray(kDigest);
+            PaddingMode padding = dataProvider->PickValueInArray(kPaddingMode);
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .RsaEncryptionKey(kKeySize, kPublicExponent)
+                    .Digest(digest)
+                    .Padding(padding)
+                    .Authorization(TAG_INCLUDE_UNIQUE_ID);
+        } break;
+        case ECDSA_SIGNING_CURVE: {
+            EcCurve ecCurve = dataProvider->PickValueInArray(kCurve);
+            Digest digest = dataProvider->PickValueInArray(kDigest);
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .EcdsaSigningKey(ecCurve)
+                    .Digest(digest)
+                    .Authorization(TAG_INCLUDE_UNIQUE_ID);
+        } break;
+        case ECDSA_SIGNING_KEY: {
+            Digest digest = dataProvider->PickValueInArray(kDigest);
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .EcdsaSigningKey(kKeySize)
+                    .Digest(digest)
+                    .Authorization(TAG_INCLUDE_UNIQUE_ID);
+        } break;
+        case AES_ENCRYPTION_KEY: {
+            Digest digest = dataProvider->PickValueInArray(kDigest);
+            PaddingMode padding = dataProvider->PickValueInArray(kPaddingMode);
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .AesEncryptionKey(kKeySize)
+                    .Digest(digest)
+                    .Padding(padding)
+                    .Authorization(TAG_INCLUDE_UNIQUE_ID);
+        } break;
+        case TRIPLE_DES: {
+            Digest digest = dataProvider->PickValueInArray(kDigest);
+            PaddingMode padding = dataProvider->PickValueInArray(kPaddingMode);
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .TripleDesEncryptionKey(kKeySize)
+                    .Digest(digest)
+                    .Padding(padding)
+                    .Authorization(TAG_INCLUDE_UNIQUE_ID);
+        } break;
+        case HMAC: {
+            Digest digest = dataProvider->PickValueInArray(kDigest);
+            PaddingMode padding = dataProvider->PickValueInArray(kPaddingMode);
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .HmacKey(kKeySize)
+                    .Digest(digest)
+                    .Padding(padding)
+                    .Authorization(TAG_INCLUDE_UNIQUE_ID);
+        } break;
+        case NO_DIGEST: {
+            Digest digest = dataProvider->PickValueInArray(kDigest);
+            PaddingMode padding = dataProvider->PickValueInArray(kPaddingMode);
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .NoDigestOrPadding()
+                    .Digest(digest)
+                    .Padding(padding)
+                    .Authorization(TAG_INCLUDE_UNIQUE_ID);
+        } break;
+        case ECB_MODE: {
+            Digest digest = dataProvider->PickValueInArray(kDigest);
+            PaddingMode padding = dataProvider->PickValueInArray(kPaddingMode);
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .EcbMode()
+                    .Digest(digest)
+                    .Padding(padding)
+                    .Authorization(TAG_INCLUDE_UNIQUE_ID);
+        } break;
+        case GSM_MODE_MIN_MAC: {
+            uint32_t minMacLength = dataProvider->ConsumeIntegral<uint32_t>();
+            Digest digest = dataProvider->PickValueInArray(kDigest);
+            PaddingMode padding = dataProvider->PickValueInArray(kPaddingMode);
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .GcmModeMinMacLen(minMacLength)
+                    .Digest(digest)
+                    .Padding(padding)
+                    .Authorization(TAG_INCLUDE_UNIQUE_ID);
+        } break;
+        case GSM_MODE_MAC: {
+            uint32_t macLength = dataProvider->ConsumeIntegral<uint32_t>();
+            Digest digest = dataProvider->PickValueInArray(kDigest);
+            PaddingMode padding = dataProvider->PickValueInArray(kPaddingMode);
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .GcmModeMacLen(macLength)
+                    .Digest(digest)
+                    .Padding(padding)
+                    .Authorization(TAG_INCLUDE_UNIQUE_ID);
+        } break;
+        case BLOCK_MODE: {
+            Digest digest = dataProvider->PickValueInArray(kDigest);
+            PaddingMode padding = dataProvider->PickValueInArray(kPaddingMode);
+            auto blockModes = {
+                    BlockMode::ECB,
+                    BlockMode::CBC,
+                    BlockMode::CTR,
+                    BlockMode::GCM,
+            };
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .BlockMode(blockModes)
+                    .Digest(digest)
+                    .Padding(padding)
+                    .Authorization(TAG_INCLUDE_UNIQUE_ID);
+        } break;
+        default:
+            break;
+    };
+    return AuthorizationSetBuilder();
+}
+
+}  // namespace android::hardware::keymaster::V4_0::fuzzer
+
+#endif  // __KEYMASTER4_COMMON_H__
diff --git a/keymaster/4.0/support/fuzzer/keymaster4_utils_fuzzer.cpp b/keymaster/4.0/support/fuzzer/keymaster4_utils_fuzzer.cpp
new file mode 100644
index 0000000..bf074e8
--- /dev/null
+++ b/keymaster/4.0/support/fuzzer/keymaster4_utils_fuzzer.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include <hardware/hw_auth_token.h>
+#include <keymasterV4_0/keymaster_utils.h>
+#include "keymaster4_common.h"
+
+namespace android::hardware::keymaster::V4_0::fuzzer {
+
+using android::hardware::keymaster::V4_0::SecurityLevel;
+using android::hardware::keymaster::V4_0::VerificationToken;
+using android::hardware::keymaster::V4_0::support::deserializeVerificationToken;
+using android::hardware::keymaster::V4_0::support::serializeVerificationToken;
+
+constexpr SecurityLevel kSecurityLevel[]{
+        SecurityLevel::SOFTWARE,
+        SecurityLevel::TRUSTED_ENVIRONMENT,
+        SecurityLevel::STRONGBOX,
+};
+constexpr size_t kMaxVectorSize = 100;
+constexpr size_t kMaxCharacters = 100;
+
+class KeyMaster4UtilsFuzzer {
+  public:
+    void process(const uint8_t* data, size_t size);
+
+  private:
+    void invokeKeyMasterUtils();
+    std::unique_ptr<FuzzedDataProvider> mFdp = nullptr;
+};
+
+void KeyMaster4UtilsFuzzer::invokeKeyMasterUtils() {
+    support::getOsVersion();
+    support::getOsPatchlevel();
+
+    VerificationToken token;
+    token.challenge = mFdp->ConsumeIntegral<uint64_t>();
+    token.timestamp = mFdp->ConsumeIntegral<uint64_t>();
+    token.securityLevel = mFdp->PickValueInArray(kSecurityLevel);
+    size_t vectorSize = mFdp->ConsumeIntegralInRange<size_t>(0, kMaxVectorSize);
+    token.mac.resize(vectorSize);
+    for (size_t n = 0; n < vectorSize; ++n) {
+        token.mac[n] = n;
+    }
+    std::optional<std::vector<uint8_t>> serialized = serializeVerificationToken(token);
+    if (serialized.has_value()) {
+        std::optional<VerificationToken> deserialized =
+                deserializeVerificationToken(serialized.value());
+    }
+
+    std::vector<uint8_t> dataVector;
+    size_t size = mFdp->ConsumeIntegralInRange<size_t>(0, sizeof(hw_auth_token_t));
+    dataVector = mFdp->ConsumeBytes<uint8_t>(size);
+    support::blob2hidlVec(dataVector.data(), dataVector.size());
+
+    support::blob2hidlVec(dataVector);
+
+    std::string str = mFdp->ConsumeRandomLengthString(kMaxCharacters);
+    support::blob2hidlVec(str);
+
+    HardwareAuthToken authToken = support::hidlVec2AuthToken(dataVector);
+    hidl_vec<uint8_t> volatile hidlVector = support::authToken2HidlVec(authToken);
+}
+
+void KeyMaster4UtilsFuzzer::process(const uint8_t* data, size_t size) {
+    mFdp = std::make_unique<FuzzedDataProvider>(data, size);
+    invokeKeyMasterUtils();
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    KeyMaster4UtilsFuzzer kmUtilsFuzzer;
+    kmUtilsFuzzer.process(data, size);
+    return 0;
+}
+
+}  // namespace android::hardware::keymaster::V4_0::fuzzer
diff --git a/keymaster/4.0/vts/OWNERS b/keymaster/4.0/vts/OWNERS
index abfb2e0..0d6fa6c 100644
--- a/keymaster/4.0/vts/OWNERS
+++ b/keymaster/4.0/vts/OWNERS
@@ -1,3 +1,4 @@
+drysdale@google.com
 jbires@google.com
 jdanis@google.com
 swillden@google.com
diff --git a/keymaster/4.0/vts/functional/Android.bp b/keymaster/4.0/vts/functional/Android.bp
index a7be660..f9a02ba 100644
--- a/keymaster/4.0/vts/functional/Android.bp
+++ b/keymaster/4.0/vts/functional/Android.bp
@@ -26,6 +26,9 @@
 cc_test {
     name: "VtsHalKeymasterV4_0TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: [
+        "keymaster_hidl_hal_test.cpp",
+    ],
     srcs: [
         "HmacKeySharingTest.cpp",
         "VerificationTokenTest.cpp",
@@ -41,11 +44,18 @@
         "general-tests",
         "vts",
     ],
+    sanitize: {
+        cfi: false,
+    },
+
 }
 
 cc_test_library {
     name: "libkeymaster4vtstest",
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: [
+        "KeymasterHidlTest.cpp",
+    ],
     srcs: [
         "KeymasterHidlTest.cpp",
     ],
diff --git a/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp b/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp
index d0ad433..315a4bd 100644
--- a/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp
+++ b/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp
@@ -443,6 +443,101 @@
         AuthorizationSetBuilder().Digest(digest).Authorization(TAG_MAC_LENGTH, mac_length));
 }
 
+void KeymasterHidlTest::CheckAesIncrementalEncryptOperation(BlockMode block_mode,
+                                                            int message_size) {
+    auto builder = AuthorizationSetBuilder()
+                           .Authorization(TAG_NO_AUTH_REQUIRED)
+                           .AesEncryptionKey(128)
+                           .BlockMode(block_mode)
+                           .Padding(PaddingMode::NONE);
+    if (block_mode == BlockMode::GCM) {
+        builder.Authorization(TAG_MIN_MAC_LENGTH, 128);
+    }
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(builder));
+
+    for (int increment = 1; increment <= message_size; ++increment) {
+        string message(message_size, 'a');
+        auto params = AuthorizationSetBuilder()
+                              .BlockMode(block_mode)
+                              .Padding(PaddingMode::NONE)
+                              .Authorization(TAG_MAC_LENGTH, 128) /* for GCM */;
+
+        AuthorizationSet output_params;
+        EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params, &output_params));
+
+        string ciphertext;
+        size_t input_consumed;
+        string to_send;
+        for (size_t i = 0; i < message.size(); i += increment) {
+            to_send.append(message.substr(i, increment));
+            EXPECT_EQ(ErrorCode::OK, Update(to_send, &ciphertext, &input_consumed));
+            EXPECT_EQ(to_send.length(), input_consumed);
+            to_send = to_send.substr(input_consumed);
+            EXPECT_EQ(0U, to_send.length());
+
+            switch (block_mode) {
+                case BlockMode::ECB:
+                case BlockMode::CBC:
+                    // Implementations must take as many blocks as possible, leaving less than
+                    // a block.
+                    EXPECT_LE(to_send.length(), 16U);
+                    break;
+                case BlockMode::GCM:
+                case BlockMode::CTR:
+                    // Implementations must always take all the data.
+                    EXPECT_EQ(0U, to_send.length());
+                    break;
+            }
+        }
+        EXPECT_EQ(ErrorCode::OK, Finish(to_send, &ciphertext)) << "Error sending " << to_send;
+
+        switch (block_mode) {
+            case BlockMode::GCM:
+                EXPECT_EQ(message.size() + 16, ciphertext.size());
+                break;
+            case BlockMode::CTR:
+                EXPECT_EQ(message.size(), ciphertext.size());
+                break;
+            case BlockMode::CBC:
+            case BlockMode::ECB:
+                EXPECT_EQ(message.size() + message.size() % 16, ciphertext.size());
+                break;
+        }
+
+        auto iv = output_params.GetTagValue(TAG_NONCE);
+        switch (block_mode) {
+            case BlockMode::CBC:
+            case BlockMode::GCM:
+            case BlockMode::CTR:
+                ASSERT_TRUE(iv.isOk()) << "No IV for block mode " << block_mode;
+                EXPECT_EQ(block_mode == BlockMode::GCM ? 12U : 16U, iv.value().size());
+                params.push_back(TAG_NONCE, iv.value());
+                break;
+
+            case BlockMode::ECB:
+                EXPECT_FALSE(iv.isOk()) << "ECB mode should not generate IV";
+                break;
+        }
+
+        EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params))
+                << "Decrypt begin() failed for block mode " << block_mode;
+
+        string plaintext;
+        for (size_t i = 0; i < ciphertext.size(); i += increment) {
+            to_send.append(ciphertext.substr(i, increment));
+            EXPECT_EQ(ErrorCode::OK, Update(to_send, &plaintext, &input_consumed));
+            to_send = to_send.substr(input_consumed);
+        }
+        ErrorCode error = Finish(to_send, &plaintext);
+        ASSERT_EQ(ErrorCode::OK, error) << "Decryption failed for block mode " << block_mode
+                                        << " and increment " << increment;
+        if (error == ErrorCode::OK) {
+            ASSERT_EQ(message, plaintext) << "Decryption didn't match for block mode " << block_mode
+                                          << " and increment " << increment;
+        }
+    }
+}
+
 void KeymasterHidlTest::CheckHmacTestVector(const string& key, const string& message, Digest digest,
                                             const string& expected_mac) {
     SCOPED_TRACE("CheckHmacTestVector");
diff --git a/keymaster/4.0/vts/functional/KeymasterHidlTest.h b/keymaster/4.0/vts/functional/KeymasterHidlTest.h
index 2ca7ea7..ad30aa7 100644
--- a/keymaster/4.0/vts/functional/KeymasterHidlTest.h
+++ b/keymaster/4.0/vts/functional/KeymasterHidlTest.h
@@ -166,6 +166,8 @@
 
     string MacMessage(const string& message, Digest digest, size_t mac_length);
 
+    void CheckAesIncrementalEncryptOperation(BlockMode block_mode, int message_size);
+
     void CheckHmacTestVector(const string& key, const string& message, Digest digest,
                              const string& expected_mac);
 
diff --git a/keymaster/4.0/vts/functional/OWNERS b/keymaster/4.0/vts/functional/OWNERS
new file mode 100644
index 0000000..2ef9086
--- /dev/null
+++ b/keymaster/4.0/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 189335
+swillden@google.com
diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
index 93fb19d..bdaaf96 100644
--- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -27,6 +27,7 @@
 #include <openssl/mem.h>
 #include <openssl/x509.h>
 
+#include <android-base/properties.h>
 #include <cutils/properties.h>
 
 #include <keymasterV4_0/attestation_record.h>
@@ -81,6 +82,12 @@
 namespace test {
 namespace {
 
+// The maximum number of times we'll attempt to verify that corruption
+// of an encrypted blob results in an error. Retries are necessary as there
+// is a small (roughly 1/256) chance that corrupting ciphertext still results
+// in valid PKCS7 padding.
+constexpr size_t kMaxPaddingCorruptionRetries = 8;
+
 template <TagType tag_type, Tag tag, typename ValueT>
 bool contains(hidl_vec<KeyParameter>& set, TypedTag<tag_type, tag> ttag, ValueT expected_value) {
     size_t count = std::count_if(set.begin(), set.end(), [&](const KeyParameter& param) {
@@ -380,6 +387,28 @@
     return property_get("ro.boot.vbmeta.device_state", value, "") != 0;
 }
 
+int get_vsr_api_level() {
+    int api_level = ::android::base::GetIntProperty("ro.board.api_level", -1);
+    if (api_level == -1) {
+        api_level = ::android::base::GetIntProperty("ro.board.first_api_level", -1);
+    }
+    if (api_level == -1) {
+        api_level = ::android::base::GetIntProperty("ro.vndk.version", -1);
+    }
+    // We really should have a VSR API level by now.  But on cuttlefish, and perhaps other weird
+    // devices, we may not.  So, we use the SDK first or current API level if needed.  If this goes
+    // wrong, it should go wrong in the direction of being too strict rather than too lenient, which
+    // should provoke someone to examine why we don't have proper VSR API level properties.
+    if (api_level == -1) {
+        api_level = ::android::base::GetIntProperty("ro.product.first_api_level", -1);
+    }
+    if (api_level == -1) {
+        api_level = ::android::base::GetIntProperty("ro.build.version.sdk", -1);
+    }
+    EXPECT_NE(api_level, -1) << "Could not find a VSR level, or equivalent.";
+    return api_level;
+}
+
 bool is_gsi() {
     char property_value[PROPERTY_VALUE_MAX] = {};
     EXPECT_NE(property_get("ro.product.system.name", property_value, ""), 0);
@@ -1706,6 +1735,7 @@
                     case PaddingMode::RSA_PSS:
                         EXPECT_GT(EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING), 0);
                         EXPECT_GT(EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, EVP_MD_size(md)), 0);
+                        EXPECT_GT(EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, md), 0);
                         break;
                     case PaddingMode::RSA_PKCS1_1_5_SIGN:
                         // PKCS1 is the default; don't need to set anything.
@@ -2853,11 +2883,22 @@
     string ciphertext = EncryptMessage(message, params);
     EXPECT_EQ(16U, ciphertext.size());
     EXPECT_NE(ciphertext, message);
-    ++ciphertext[ciphertext.size() / 2];
 
-    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params));
-    string plaintext;
-    EXPECT_EQ(ErrorCode::INVALID_INPUT_LENGTH, Finish(message, &plaintext));
+    for (size_t i = 0; i < kMaxPaddingCorruptionRetries; ++i) {
+        ++ciphertext[ciphertext.size() / 2];
+
+        EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params));
+        string plaintext;
+        ErrorCode error = Finish(ciphertext, &plaintext);
+        if (error == ErrorCode::INVALID_ARGUMENT) {
+            // This is the expected error, we can exit the test now.
+            return;
+        } else {
+            // Very small chance we got valid decryption, so try again.
+            ASSERT_EQ(error, ErrorCode::OK);
+        }
+    }
+    FAIL() << "Corrupt ciphertext should have failed to decrypt by now.";
 }
 
 HidlBuf CopyIv(const AuthorizationSet& set) {
@@ -2914,105 +2955,39 @@
 }
 
 /*
- * EncryptionOperationsTest.AesIncremental
+ * EncryptionOperationsTest.AesEcbIncremental
  *
- * Verifies that AES works, all modes, when provided data in various size increments.
+ * Verifies that AES works for ECB block mode, when provided data in various size increments.
  */
-TEST_P(EncryptionOperationsTest, AesIncremental) {
-    auto block_modes = {
-        BlockMode::ECB, BlockMode::CBC, BlockMode::CTR, BlockMode::GCM,
-    };
+TEST_P(EncryptionOperationsTest, AesEcbIncremental) {
+    CheckAesIncrementalEncryptOperation(BlockMode::ECB, 240);
+}
 
-    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                             .Authorization(TAG_NO_AUTH_REQUIRED)
-                                             .AesEncryptionKey(128)
-                                             .BlockMode(block_modes)
-                                             .Padding(PaddingMode::NONE)
-                                             .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+/*
+ * EncryptionOperationsTest.AesCbcIncremental
+ *
+ * Verifies that AES works for CBC block mode, when provided data in various size increments.
+ */
+TEST_P(EncryptionOperationsTest, AesCbcIncremental) {
+    CheckAesIncrementalEncryptOperation(BlockMode::CBC, 240);
+}
 
-    for (int increment = 1; increment <= 240; ++increment) {
-        for (auto block_mode : block_modes) {
-            string message(240, 'a');
-            auto params = AuthorizationSetBuilder()
-                              .BlockMode(block_mode)
-                              .Padding(PaddingMode::NONE)
-                              .Authorization(TAG_MAC_LENGTH, 128) /* for GCM */;
+/*
+ * EncryptionOperationsTest.AesCtrIncremental
+ *
+ * Verifies that AES works for CTR block mode, when provided data in various size increments.
+ */
+TEST_P(EncryptionOperationsTest, AesCtrIncremental) {
+    CheckAesIncrementalEncryptOperation(BlockMode::CTR, 240);
+}
 
-            AuthorizationSet output_params;
-            EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params, &output_params));
-
-            string ciphertext;
-            size_t input_consumed;
-            string to_send;
-            for (size_t i = 0; i < message.size(); i += increment) {
-                to_send.append(message.substr(i, increment));
-                EXPECT_EQ(ErrorCode::OK, Update(to_send, &ciphertext, &input_consumed));
-                EXPECT_EQ(to_send.length(), input_consumed);
-                to_send = to_send.substr(input_consumed);
-                EXPECT_EQ(0U, to_send.length());
-
-                switch (block_mode) {
-                    case BlockMode::ECB:
-                    case BlockMode::CBC:
-                        // Implementations must take as many blocks as possible, leaving less than
-                        // a block.
-                        EXPECT_LE(to_send.length(), 16U);
-                        break;
-                    case BlockMode::GCM:
-                    case BlockMode::CTR:
-                        // Implementations must always take all the data.
-                        EXPECT_EQ(0U, to_send.length());
-                        break;
-                }
-            }
-            EXPECT_EQ(ErrorCode::OK, Finish(to_send, &ciphertext)) << "Error sending " << to_send;
-
-            switch (block_mode) {
-                case BlockMode::GCM:
-                    EXPECT_EQ(message.size() + 16, ciphertext.size());
-                    break;
-                case BlockMode::CTR:
-                    EXPECT_EQ(message.size(), ciphertext.size());
-                    break;
-                case BlockMode::CBC:
-                case BlockMode::ECB:
-                    EXPECT_EQ(message.size() + message.size() % 16, ciphertext.size());
-                    break;
-            }
-
-            auto iv = output_params.GetTagValue(TAG_NONCE);
-            switch (block_mode) {
-                case BlockMode::CBC:
-                case BlockMode::GCM:
-                case BlockMode::CTR:
-                    ASSERT_TRUE(iv.isOk()) << "No IV for block mode " << block_mode;
-                    EXPECT_EQ(block_mode == BlockMode::GCM ? 12U : 16U, iv.value().size());
-                    params.push_back(TAG_NONCE, iv.value());
-                    break;
-
-                case BlockMode::ECB:
-                    EXPECT_FALSE(iv.isOk()) << "ECB mode should not generate IV";
-                    break;
-            }
-
-            EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params))
-                << "Decrypt begin() failed for block mode " << block_mode;
-
-            string plaintext;
-            for (size_t i = 0; i < ciphertext.size(); i += increment) {
-                to_send.append(ciphertext.substr(i, increment));
-                EXPECT_EQ(ErrorCode::OK, Update(to_send, &plaintext, &input_consumed));
-                to_send = to_send.substr(input_consumed);
-            }
-            ErrorCode error = Finish(to_send, &plaintext);
-            ASSERT_EQ(ErrorCode::OK, error) << "Decryption failed for block mode " << block_mode
-                                            << " and increment " << increment;
-            if (error == ErrorCode::OK) {
-                ASSERT_EQ(message, plaintext) << "Decryption didn't match for block mode "
-                                              << block_mode << " and increment " << increment;
-            }
-        }
-    }
+/*
+ * EncryptionOperationsTest.AesGcmIncremental
+ *
+ * Verifies that AES works for GCM block mode, when provided data in various size increments.
+ */
+TEST_P(EncryptionOperationsTest, AesGcmIncremental) {
+    CheckAesIncrementalEncryptOperation(BlockMode::GCM, 240);
 }
 
 struct AesCtrSp80038aTestVector {
@@ -3153,6 +3128,49 @@
 }
 
 /*
+ * EncryptionOperationsTest.AesCbcZeroInputSuccessb
+ *
+ * Verifies that keymaster generates correct output on zero-input with
+ * NonePadding mode
+ */
+TEST_P(EncryptionOperationsTest, AesCbcZeroInputSuccess) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                                 .Authorization(TAG_NO_AUTH_REQUIRED)
+                                                 .AesEncryptionKey(128)
+                                                 .BlockMode(BlockMode::CBC)
+                                                 .Padding(PaddingMode::NONE, PaddingMode::PKCS7)));
+
+    // Zero input message
+    string message = "";
+    for (auto padding : {PaddingMode::NONE, PaddingMode::PKCS7}) {
+        auto params = AuthorizationSetBuilder().BlockMode(BlockMode::CBC).Padding(padding);
+        AuthorizationSet out_params;
+        string ciphertext1 = EncryptMessage(message, params, &out_params);
+        HidlBuf iv1 = CopyIv(out_params);
+        if (padding == PaddingMode::NONE)
+            EXPECT_EQ(message.size(), ciphertext1.size()) << "PaddingMode: " << padding;
+        else
+            EXPECT_EQ(message.size(), ciphertext1.size() - 16) << "PaddingMode: " << padding;
+
+        out_params.Clear();
+
+        string ciphertext2 = EncryptMessage(message, params, &out_params);
+        HidlBuf iv2 = CopyIv(out_params);
+        if (padding == PaddingMode::NONE)
+            EXPECT_EQ(message.size(), ciphertext2.size()) << "PaddingMode: " << padding;
+        else
+            EXPECT_EQ(message.size(), ciphertext2.size() - 16) << "PaddingMode: " << padding;
+
+        // IVs should be random
+        EXPECT_NE(iv1, iv2) << "PaddingMode: " << padding;
+
+        params.push_back(TAG_NONCE, iv1);
+        string plaintext = DecryptMessage(ciphertext1, params);
+        EXPECT_EQ(message, plaintext) << "PaddingMode: " << padding;
+    }
+}
+
+/*
  * EncryptionOperationsTest.AesCallerNonce
  *
  * Verifies that AES caller-provided nonces work correctly.
@@ -3880,17 +3898,30 @@
     string ciphertext = EncryptMessage(message, BlockMode::ECB, PaddingMode::PKCS7);
     EXPECT_EQ(8U, ciphertext.size());
     EXPECT_NE(ciphertext, message);
-    ++ciphertext[ciphertext.size() / 2];
 
     AuthorizationSetBuilder begin_params;
     begin_params.push_back(TAG_BLOCK_MODE, BlockMode::ECB);
     begin_params.push_back(TAG_PADDING, PaddingMode::PKCS7);
-    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params));
-    string plaintext;
-    size_t input_consumed;
-    EXPECT_EQ(ErrorCode::OK, Update(ciphertext, &plaintext, &input_consumed));
-    EXPECT_EQ(ciphertext.size(), input_consumed);
-    EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, Finish(&plaintext));
+
+    for (size_t i = 0; i < kMaxPaddingCorruptionRetries; ++i) {
+        ++ciphertext[ciphertext.size() / 2];
+
+        EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params));
+        string plaintext;
+
+        size_t input_consumed;
+        EXPECT_EQ(ErrorCode::OK, Update(ciphertext, &plaintext, &input_consumed));
+        EXPECT_EQ(ciphertext.size(), input_consumed);
+        ErrorCode error = Finish(&plaintext);
+        if (error == ErrorCode::INVALID_ARGUMENT) {
+            // This is the expected error, we can exit the test now.
+            return;
+        } else {
+            // Very small chance we got valid decryption, so try again.
+            ASSERT_EQ(error, ErrorCode::OK);
+        }
+    }
+    FAIL() << "Corrupt ciphertext should have failed to decrypt by now.";
 }
 
 struct TripleDesTestVector {
@@ -4191,18 +4222,28 @@
     string ciphertext = EncryptMessage(message, BlockMode::CBC, PaddingMode::PKCS7, &iv);
     EXPECT_EQ(8U, ciphertext.size());
     EXPECT_NE(ciphertext, message);
-    ++ciphertext[ciphertext.size() / 2];
 
     auto begin_params = AuthorizationSetBuilder()
                             .BlockMode(BlockMode::CBC)
                             .Padding(PaddingMode::PKCS7)
                             .Authorization(TAG_NONCE, iv);
-    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params));
-    string plaintext;
-    size_t input_consumed;
-    EXPECT_EQ(ErrorCode::OK, Update(ciphertext, &plaintext, &input_consumed));
-    EXPECT_EQ(ciphertext.size(), input_consumed);
-    EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, Finish(&plaintext));
+    for (size_t i = 0; i < kMaxPaddingCorruptionRetries; ++i) {
+        ++ciphertext[ciphertext.size() / 2];
+        EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params));
+        string plaintext;
+        size_t input_consumed;
+        EXPECT_EQ(ErrorCode::OK, Update(ciphertext, &plaintext, &input_consumed));
+        EXPECT_EQ(ciphertext.size(), input_consumed);
+        ErrorCode error = Finish(&plaintext);
+        if (error == ErrorCode::INVALID_ARGUMENT) {
+            // This is the expected error, we can exit the test now.
+            return;
+        } else {
+            // Very small chance we got valid decryption, so try again.
+            ASSERT_EQ(error, ErrorCode::OK);
+        }
+    }
+    FAIL() << "Corrupt ciphertext should have failed to decrypt by now.";
 }
 
 /*
@@ -4815,6 +4856,18 @@
 
 INSTANTIATE_KEYMASTER_HIDL_TEST(TransportLimitTest);
 
+using VsrRequirementTest = KeymasterHidlTest;
+
+TEST_P(VsrRequirementTest, Vsr13Test) {
+    int vsr_api_level = get_vsr_api_level();
+    if (vsr_api_level < 33) {
+        GTEST_SKIP() << "Applies only to VSR API level 33, this device is: " << vsr_api_level;
+    }
+    FAIL() << "VSR 13+ requires KeyMint version 2";
+}
+
+INSTANTIATE_KEYMASTER_HIDL_TEST(VsrRequirementTest);
+
 }  // namespace test
 }  // namespace V4_0
 }  // namespace keymaster
diff --git a/keymaster/4.1/vts/OWNERS b/keymaster/4.1/vts/OWNERS
index 2b2ad2a..24ed042 100644
--- a/keymaster/4.1/vts/OWNERS
+++ b/keymaster/4.1/vts/OWNERS
@@ -1,3 +1,4 @@
+drysdale@google.com
 jbires@google.com
 jdanis@google.com
 swillden@google.com
diff --git a/keymaster/4.1/vts/functional/Android.bp b/keymaster/4.1/vts/functional/Android.bp
index c650bec..547ce38 100644
--- a/keymaster/4.1/vts/functional/Android.bp
+++ b/keymaster/4.1/vts/functional/Android.bp
@@ -48,4 +48,7 @@
         "general-tests",
         "vts",
     ],
+    sanitize: {
+        cfi: false,
+    },
 }
diff --git a/keymaster/4.1/vts/functional/OWNERS b/keymaster/4.1/vts/functional/OWNERS
new file mode 100644
index 0000000..2ef9086
--- /dev/null
+++ b/keymaster/4.1/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 189335
+swillden@google.com
diff --git a/light/aidl/default/Android.bp b/light/aidl/default/Android.bp
index 459b8e2..2ccf140 100644
--- a/light/aidl/default/Android.bp
+++ b/light/aidl/default/Android.bp
@@ -16,7 +16,7 @@
     shared_libs: [
         "libbase",
         "libbinder_ndk",
-        "android.hardware.light-V1-ndk_platform",
+        "android.hardware.light-V1-ndk",
     ],
     srcs: [
         "Lights.cpp",
diff --git a/light/aidl/default/main.cpp b/light/aidl/default/main.cpp
index a860bf4..54e1316 100644
--- a/light/aidl/default/main.cpp
+++ b/light/aidl/default/main.cpp
@@ -28,7 +28,7 @@
 
     const std::string instance = std::string() + Lights::descriptor + "/default";
     binder_status_t status = AServiceManager_addService(lights->asBinder().get(), instance.c_str());
-    CHECK(status == STATUS_OK);
+    CHECK_EQ(status, STATUS_OK);
 
     ABinderProcess_joinThreadPool();
     return EXIT_FAILURE;  // should not reached
diff --git a/media/omx/1.0/vts/OWNERS b/media/omx/1.0/vts/OWNERS
index e0e0dd1..9e390c2 100644
--- a/media/omx/1.0/vts/OWNERS
+++ b/media/omx/1.0/vts/OWNERS
@@ -1,7 +1,5 @@
+# Bug component: 25690
 # Media team
-pawin@google.com
+taklee@google.com
+wonsik@google.com
 lajos@google.com
-
-# VTS team
-yim@google.com
-zhuoyao@google.com
\ No newline at end of file
diff --git a/media/omx/1.0/vts/functional/common/media_hidl_test_common.h b/media/omx/1.0/vts/functional/common/media_hidl_test_common.h
index eddf83f..6caac63 100644
--- a/media/omx/1.0/vts/functional/common/media_hidl_test_common.h
+++ b/media/omx/1.0/vts/functional/common/media_hidl_test_common.h
@@ -203,9 +203,8 @@
             }
             int64_t delayUs = finishBy - android::ALooper::GetNowUs();
             if (delayUs < 0) return toStatus(android::TIMED_OUT);
-            (timeoutUs < 0)
-                ? msgCondition.wait(msgLock)
-                : msgCondition.waitRelative(msgLock, delayUs * 1000ll);
+            (timeoutUs < 0) ? msgCondition.wait(msgLock)
+                            : msgCondition.waitRelative(msgLock, delayUs * 1000LL);
         }
     }
 
diff --git a/media/omx/1.0/vts/functional/component/Android.bp b/media/omx/1.0/vts/functional/component/Android.bp
index 9d4d092..7b8ec9d 100644
--- a/media/omx/1.0/vts/functional/component/Android.bp
+++ b/media/omx/1.0/vts/functional/component/Android.bp
@@ -26,6 +26,7 @@
 cc_test {
     name: "VtsHalMediaOmxV1_0TargetComponentTest",
     defaults: ["VtsHalMediaOmxV1_0Defaults"],
+    tidy_timeout_srcs: ["VtsHalMediaOmxV1_0TargetComponentTest.cpp"],
     srcs: ["VtsHalMediaOmxV1_0TargetComponentTest.cpp"],
     test_suites: [
         "vts",
diff --git a/media/omx/1.0/vts/functional/store/VtsHalMediaOmxV1_0TargetStoreTest.cpp b/media/omx/1.0/vts/functional/store/VtsHalMediaOmxV1_0TargetStoreTest.cpp
index 8699de3..5fa13e7 100644
--- a/media/omx/1.0/vts/functional/store/VtsHalMediaOmxV1_0TargetStoreTest.cpp
+++ b/media/omx/1.0/vts/functional/store/VtsHalMediaOmxV1_0TargetStoreTest.cpp
@@ -20,8 +20,11 @@
 #endif
 
 #include <android-base/logging.h>
+#include <android-base/properties.h>
 #include <android-base/strings.h>
+#include <android/api-level.h>
 
+#include <VtsCoreUtil.h>
 #include <android/hardware/media/omx/1.0/IOmx.h>
 #include <android/hardware/media/omx/1.0/IOmxNode.h>
 #include <android/hardware/media/omx/1.0/IOmxObserver.h>
@@ -371,6 +374,42 @@
     }
 }
 
+static int getFirstApiLevel() {
+    return android::base::GetIntProperty("ro.product.first_api_level", __ANDROID_API_T__);
+}
+
+static bool isTV() {
+    return testing::deviceSupportsFeature("android.software.leanback");
+}
+
+// list components and roles.
+TEST_P(StoreHidlTest, OmxCodecAllowedTest) {
+    hidl_vec<IOmx::ComponentInfo> componentInfos = getComponentInfoList(omx);
+    for (IOmx::ComponentInfo info : componentInfos) {
+        for (std::string role : info.mRoles) {
+            if (role.find("video_decoder") != std::string::npos ||
+                role.find("video_encoder") != std::string::npos) {
+                // Codec2 is not mandatory on Android TV devices that launched with Android S
+                if (isTV()) {
+                    ASSERT_LT(getFirstApiLevel(), __ANDROID_API_T__)
+                            << " Component: " << info.mName.c_str() << " Role: " << role.c_str()
+                            << " not allowed for devices launching with Android T and above";
+                } else {
+                    ASSERT_LT(getFirstApiLevel(), __ANDROID_API_S__)
+                            << " Component: " << info.mName.c_str() << " Role: " << role.c_str()
+                            << " not allowed for devices launching with Android S and above";
+                }
+            }
+            if (role.find("audio_decoder") != std::string::npos ||
+                role.find("audio_encoder") != std::string::npos) {
+                ASSERT_LT(getFirstApiLevel(), __ANDROID_API_T__)
+                        << " Component: " << info.mName.c_str() << " Role: " << role.c_str()
+                        << " not allowed for devices launching with Android T and above";
+            }
+        }
+    }
+}
+
 // list components and roles.
 TEST_P(StoreHidlTest, ListNodes) {
     description("enumerate component and roles");
diff --git a/memtrack/OWNERS b/memtrack/OWNERS
new file mode 100644
index 0000000..a182ed9
--- /dev/null
+++ b/memtrack/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 30545
+connoro@google.com
diff --git a/memtrack/aidl/default/Android.bp b/memtrack/aidl/default/Android.bp
index 7a7feea..6c77177 100644
--- a/memtrack/aidl/default/Android.bp
+++ b/memtrack/aidl/default/Android.bp
@@ -30,7 +30,7 @@
     shared_libs: [
         "libbase",
         "libbinder_ndk",
-        "android.hardware.memtrack-V1-ndk_platform",
+        "android.hardware.memtrack-V1-ndk",
     ],
     srcs: [
         "main.cpp",
diff --git a/memtrack/aidl/default/main.cpp b/memtrack/aidl/default/main.cpp
index d063d2a..5cf5f94 100644
--- a/memtrack/aidl/default/main.cpp
+++ b/memtrack/aidl/default/main.cpp
@@ -29,7 +29,7 @@
     const std::string instance = std::string() + Memtrack::descriptor + "/default";
     binder_status_t status =
             AServiceManager_addService(memtrack->asBinder().get(), instance.c_str());
-    CHECK(status == STATUS_OK);
+    CHECK_EQ(status, STATUS_OK);
 
     ABinderProcess_joinThreadPool();
     return EXIT_FAILURE;  // Unreachable
diff --git a/memtrack/aidl/vts/Android.bp b/memtrack/aidl/vts/Android.bp
index 8614b47..f54388a 100644
--- a/memtrack/aidl/vts/Android.bp
+++ b/memtrack/aidl/vts/Android.bp
@@ -19,7 +19,7 @@
         "libvintf",
     ],
     static_libs: [
-        "android.hardware.memtrack-V1-ndk_platform",
+        "android.hardware.memtrack-V1-ndk",
     ],
     test_suites: [
         "vts",
diff --git a/neuralnetworks/1.0/utils/Android.bp b/neuralnetworks/1.0/utils/Android.bp
index 0ad9926..ad30e30 100644
--- a/neuralnetworks/1.0/utils/Android.bp
+++ b/neuralnetworks/1.0/utils/Android.bp
@@ -31,39 +31,40 @@
     export_include_dirs: ["include"],
     cflags: ["-Wthread-safety"],
     static_libs: [
+        "android.hardware.neuralnetworks@1.0",
+        "libarect",
         "neuralnetworks_types",
         "neuralnetworks_utils_hal_common",
     ],
-    shared_libs: [
-        "android.hardware.neuralnetworks@1.0",
-    ],
-    export_static_lib_headers: [
-        "neuralnetworks_utils_hal_common",
-    ],
+    target: {
+        android: {
+            shared_libs: ["libnativewindow"],
+        },
+    },
 }
 
 cc_test {
     name: "neuralnetworks_utils_hal_1_0_test",
+    host_supported: true,
     srcs: ["test/*.cpp"],
     static_libs: [
         "android.hardware.neuralnetworks@1.0",
         "libgmock",
-        "libneuralnetworks_common",
         "neuralnetworks_types",
         "neuralnetworks_utils_hal_common",
         "neuralnetworks_utils_hal_1_0",
     ],
     shared_libs: [
-        "android.hidl.allocator@1.0",
-        "android.hidl.memory@1.0",
         "libbase",
         "libcutils",
-        "libfmq",
         "libhidlbase",
-        "libhidlmemory",
         "liblog",
-        "libnativewindow",
         "libutils",
     ],
+    target: {
+        android: {
+            shared_libs: ["libnativewindow"],
+        },
+    },
     test_suites: ["general-tests"],
 }
diff --git a/neuralnetworks/1.0/utils/OWNERS b/neuralnetworks/1.0/utils/OWNERS
deleted file mode 100644
index e4feee3..0000000
--- a/neuralnetworks/1.0/utils/OWNERS
+++ /dev/null
@@ -1,11 +0,0 @@
-# Neuralnetworks team
-butlermichael@google.com
-dgross@google.com
-galarragas@google.com
-jeanluc@google.com
-levp@google.com
-miaowang@google.com
-pszczepaniak@google.com
-slavash@google.com
-vddang@google.com
-xusongw@google.com
diff --git a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Burst.h b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Burst.h
index 8bd2fbe..cef76c6 100644
--- a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Burst.h
+++ b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Burst.h
@@ -45,12 +45,15 @@
 
     nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
             const nn::Request& request, nn::MeasureTiming measure,
-            const nn::OptionalTimePoint& deadline,
-            const nn::OptionalDuration& loopTimeoutDuration) const override;
+            const nn::OptionalTimePoint& deadline, const nn::OptionalDuration& loopTimeoutDuration,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
 
     nn::GeneralResult<nn::SharedExecution> createReusableExecution(
             const nn::Request& request, nn::MeasureTiming measure,
-            const nn::OptionalDuration& loopTimeoutDuration) const override;
+            const nn::OptionalDuration& loopTimeoutDuration,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
 
   private:
     const nn::SharedPreparedModel kPreparedModel;
diff --git a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Callbacks.h b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Callbacks.h
index 3b32e1d..244001f 100644
--- a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Callbacks.h
+++ b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Callbacks.h
@@ -24,9 +24,10 @@
 #include <nnapi/Result.h>
 #include <nnapi/Types.h>
 #include <nnapi/hal/CommonUtils.h>
-#include <nnapi/hal/ProtectCallback.h>
 #include <nnapi/hal/TransferValue.h>
 
+#include "nnapi/hal/1.0/ProtectCallback.h"
+
 // See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
 // lifetimes across processes and for protecting asynchronous calls across HIDL.
 
@@ -40,7 +41,7 @@
 
 // Converts the results of IDevice::prepareModel* to the NN canonical format. On success, this
 // function returns with a non-null nn::SharedPreparedModel with a feature level of
-// nn::Version::ANDROID_OC_MR1. On failure, this function returns with the appropriate
+// nn::kVersionFeatureLevel1. On failure, this function returns with the appropriate
 // nn::GeneralError.
 nn::GeneralResult<nn::SharedPreparedModel> prepareModelCallback(
         ErrorStatus status, const sp<IPreparedModel>& preparedModel);
diff --git a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Conversions.h b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Conversions.h
index 5d4bdbc..a770d06 100644
--- a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Conversions.h
+++ b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Conversions.h
@@ -36,6 +36,7 @@
 GeneralResult<Operation> unvalidatedConvert(const hal::V1_0::Operation& operation);
 GeneralResult<Model::OperandValues> unvalidatedConvert(
         const hardware::hidl_vec<uint8_t>& operandValues);
+GeneralResult<SharedHandle> unvalidatedConvert(const hardware::hidl_handle& handle);
 GeneralResult<SharedMemory> unvalidatedConvert(const hardware::hidl_memory& memory);
 GeneralResult<Model> unvalidatedConvert(const hal::V1_0::Model& model);
 GeneralResult<Request::Argument> unvalidatedConvert(
@@ -65,6 +66,7 @@
 nn::GeneralResult<Operation> unvalidatedConvert(const nn::Operation& operation);
 nn::GeneralResult<hidl_vec<uint8_t>> unvalidatedConvert(
         const nn::Model::OperandValues& operandValues);
+nn::GeneralResult<hidl_handle> unvalidatedConvert(const nn::SharedHandle& handle);
 nn::GeneralResult<hidl_memory> unvalidatedConvert(const nn::SharedMemory& memory);
 nn::GeneralResult<Model> unvalidatedConvert(const nn::Model& model);
 nn::GeneralResult<RequestArgument> unvalidatedConvert(const nn::Request::Argument& requestArgument);
diff --git a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Device.h b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Device.h
index db3b2ad..d7c43ef 100644
--- a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Device.h
+++ b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Device.h
@@ -24,7 +24,8 @@
 #include <nnapi/Result.h>
 #include <nnapi/Types.h>
 #include <nnapi/hal/CommonUtils.h>
-#include <nnapi/hal/ProtectCallback.h>
+
+#include "nnapi/hal/1.0/ProtectCallback.h"
 
 #include <functional>
 #include <memory>
@@ -64,8 +65,9 @@
     nn::GeneralResult<nn::SharedPreparedModel> prepareModel(
             const nn::Model& model, nn::ExecutionPreference preference, nn::Priority priority,
             nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
-            const std::vector<nn::SharedHandle>& dataCache,
-            const nn::CacheToken& token) const override;
+            const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
 
     nn::GeneralResult<nn::SharedPreparedModel> prepareModelFromCache(
             nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
diff --git a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Execution.h b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Execution.h
index e201e25..66497c2 100644
--- a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Execution.h
+++ b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Execution.h
@@ -22,9 +22,9 @@
 #include <nnapi/Result.h>
 #include <nnapi/Types.h>
 #include <nnapi/hal/CommonUtils.h>
-#include <nnapi/hal/ProtectCallback.h>
 
 #include "PreparedModel.h"
+#include "nnapi/hal/1.0/ProtectCallback.h"
 
 #include <memory>
 #include <utility>
diff --git a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/HandleError.h b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/HandleError.h
new file mode 100644
index 0000000..8e02633
--- /dev/null
+++ b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/HandleError.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_0_UTILS_HANDLE_ERROR_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_0_UTILS_HANDLE_ERROR_H
+
+#include <android/hidl/base/1.0/IBase.h>
+#include <hidl/HidlSupport.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+
+#include <type_traits>
+
+namespace android::hardware::neuralnetworks::utils {
+
+template <typename Type>
+nn::GeneralResult<Type> handleTransportError(const Return<Type>& ret) {
+    if (ret.isDeadObject()) {
+        return nn::error(nn::ErrorStatus::DEAD_OBJECT)
+               << "Return<>::isDeadObject returned true: " << ret.description();
+    }
+    if (!ret.isOk()) {
+        return nn::error(nn::ErrorStatus::GENERAL_FAILURE)
+               << "Return<>::isOk returned false: " << ret.description();
+    }
+    if constexpr (!std::is_same_v<Type, void>) {
+        return static_cast<Type>(ret);
+    } else {
+        return {};
+    }
+}
+
+#define HANDLE_TRANSPORT_FAILURE(ret)                                                        \
+    ({                                                                                       \
+        auto result = ::android::hardware::neuralnetworks::utils::handleTransportError(ret); \
+        if (!result.has_value()) {                                                           \
+            return NN_ERROR(result.error().code) << result.error().message;                  \
+        }                                                                                    \
+        std::move(result).value();                                                           \
+    })
+
+#define HANDLE_STATUS_HIDL(status)                                                            \
+    if (const ::android::nn::ErrorStatus canonical = ::android::nn::convert(status).value_or( \
+                ::android::nn::ErrorStatus::GENERAL_FAILURE);                                 \
+        canonical == ::android::nn::ErrorStatus::NONE) {                                      \
+    } else                                                                                    \
+        return NN_ERROR(canonical)
+
+}  // namespace android::hardware::neuralnetworks::utils
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_0_UTILS_HANDLE_ERROR_H
diff --git a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/PreparedModel.h b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/PreparedModel.h
index 48be595..337c132 100644
--- a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/PreparedModel.h
+++ b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/PreparedModel.h
@@ -22,7 +22,8 @@
 #include <nnapi/Result.h>
 #include <nnapi/Types.h>
 #include <nnapi/hal/CommonUtils.h>
-#include <nnapi/hal/ProtectCallback.h>
+
+#include "nnapi/hal/1.0/ProtectCallback.h"
 
 #include <memory>
 #include <tuple>
@@ -48,18 +49,23 @@
 
     nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
             const nn::Request& request, nn::MeasureTiming measure,
-            const nn::OptionalTimePoint& deadline,
-            const nn::OptionalDuration& loopTimeoutDuration) const override;
+            const nn::OptionalTimePoint& deadline, const nn::OptionalDuration& loopTimeoutDuration,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
 
     nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>> executeFenced(
             const nn::Request& request, const std::vector<nn::SyncFence>& waitFor,
             nn::MeasureTiming measure, const nn::OptionalTimePoint& deadline,
             const nn::OptionalDuration& loopTimeoutDuration,
-            const nn::OptionalDuration& timeoutDurationAfterFence) const override;
+            const nn::OptionalDuration& timeoutDurationAfterFence,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
 
     nn::GeneralResult<nn::SharedExecution> createReusableExecution(
             const nn::Request& request, nn::MeasureTiming measure,
-            const nn::OptionalDuration& loopTimeoutDuration) const override;
+            const nn::OptionalDuration& loopTimeoutDuration,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
 
     nn::GeneralResult<nn::SharedBurst> configureExecutionBurst() const override;
 
diff --git a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/ProtectCallback.h b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/ProtectCallback.h
new file mode 100644
index 0000000..7418cfa
--- /dev/null
+++ b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/ProtectCallback.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_0_UTILS_PROTECT_CALLBACK_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_0_UTILS_PROTECT_CALLBACK_H
+
+#include <android-base/scopeguard.h>
+#include <android-base/thread_annotations.h>
+#include <android/hidl/base/1.0/IBase.h>
+#include <hidl/HidlSupport.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+
+#include <functional>
+#include <mutex>
+#include <vector>
+
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
+// lifetimes across processes and for protecting asynchronous calls across HIDL.
+
+namespace android::hardware::neuralnetworks::utils {
+
+class IProtectedCallback {
+  public:
+    /**
+     * Marks this object as a dead object.
+     */
+    virtual void notifyAsDeadObject() = 0;
+
+    // Public virtual destructor to allow objects to be stored (and destroyed) as smart pointers.
+    // E.g., std::unique_ptr<IProtectedCallback>.
+    virtual ~IProtectedCallback() = default;
+
+  protected:
+    // Protect the non-destructor special member functions to prevent object slicing.
+    IProtectedCallback() = default;
+    IProtectedCallback(const IProtectedCallback&) = default;
+    IProtectedCallback(IProtectedCallback&&) noexcept = default;
+    IProtectedCallback& operator=(const IProtectedCallback&) = default;
+    IProtectedCallback& operator=(IProtectedCallback&&) noexcept = default;
+};
+
+// Thread safe class
+class DeathRecipient final : public hidl_death_recipient {
+  public:
+    void serviceDied(uint64_t cookie, const wp<hidl::base::V1_0::IBase>& who) override;
+    // Precondition: `killable` must be non-null.
+    void add(IProtectedCallback* killable) const;
+    // Precondition: `killable` must be non-null.
+    void remove(IProtectedCallback* killable) const;
+
+  private:
+    mutable std::mutex mMutex;
+    mutable bool mIsDeadObject GUARDED_BY(mMutex) = false;
+    mutable std::vector<IProtectedCallback*> mObjects GUARDED_BY(mMutex);
+};
+
+class DeathHandler final {
+  public:
+    static nn::GeneralResult<DeathHandler> create(sp<hidl::base::V1_0::IBase> object);
+
+    DeathHandler(const DeathHandler&) = delete;
+    DeathHandler(DeathHandler&&) noexcept = default;
+    DeathHandler& operator=(const DeathHandler&) = delete;
+    DeathHandler& operator=(DeathHandler&&) noexcept = delete;
+    ~DeathHandler();
+
+    using Cleanup = std::function<void()>;
+    using Hold = base::ScopeGuard<Cleanup>;
+
+    // Precondition: `killable` must be non-null.
+    // `killable` must outlive the return value `Hold`.
+    [[nodiscard]] Hold protectCallback(IProtectedCallback* killable) const;
+
+    // Precondition: `killable` must be non-null.
+    // `killable` must outlive the `DeathHandler`.
+    void protectCallbackForLifetimeOfDeathHandler(IProtectedCallback* killable) const;
+
+  private:
+    DeathHandler(sp<hidl::base::V1_0::IBase> object, sp<DeathRecipient> deathRecipient);
+
+    sp<hidl::base::V1_0::IBase> mObject;
+    sp<DeathRecipient> mDeathRecipient;
+};
+
+}  // namespace android::hardware::neuralnetworks::utils
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_0_UTILS_PROTECT_CALLBACK_H
diff --git a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Utils.h b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Utils.h
index 1baabdf..7710a7e 100644
--- a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Utils.h
+++ b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Utils.h
@@ -25,11 +25,10 @@
 #include <nnapi/TypeUtils.h>
 #include <nnapi/Types.h>
 #include <nnapi/Validation.h>
-#include <nnapi/hal/HandleError.h>
 
 namespace android::hardware::neuralnetworks::V1_0::utils {
 
-constexpr auto kVersion = nn::Version::ANDROID_OC_MR1;
+constexpr auto kVersion = nn::kVersionFeatureLevel1;
 
 template <typename Type>
 nn::Result<void> validate(const Type& halObject) {
@@ -50,9 +49,9 @@
 }
 
 template <typename Type>
-nn::GeneralResult<void> compliantVersion(const Type& canonical) {
-    const auto version = NN_TRY(hal::utils::makeGeneralFailure(nn::validate(canonical)));
-    if (version > kVersion) {
+nn::Result<void> compliantVersion(const Type& canonical) {
+    const auto version = NN_TRY(nn::validate(canonical));
+    if (!nn::isCompliantVersion(version, kVersion)) {
         return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion;
     }
     return {};
diff --git a/neuralnetworks/1.0/utils/src/Burst.cpp b/neuralnetworks/1.0/utils/src/Burst.cpp
index 1284721..3642bc6 100644
--- a/neuralnetworks/1.0/utils/src/Burst.cpp
+++ b/neuralnetworks/1.0/utils/src/Burst.cpp
@@ -50,15 +50,20 @@
 
 nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> Burst::execute(
         const nn::Request& request, nn::MeasureTiming measure,
-        const nn::OptionalTimePoint& deadline,
-        const nn::OptionalDuration& loopTimeoutDuration) const {
-    return kPreparedModel->execute(request, measure, deadline, loopTimeoutDuration);
+        const nn::OptionalTimePoint& deadline, const nn::OptionalDuration& loopTimeoutDuration,
+        const std::vector<nn::TokenValuePair>& hints,
+        const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const {
+    return kPreparedModel->execute(request, measure, deadline, loopTimeoutDuration, hints,
+                                   extensionNameToPrefix);
 }
 
 nn::GeneralResult<nn::SharedExecution> Burst::createReusableExecution(
         const nn::Request& request, nn::MeasureTiming measure,
-        const nn::OptionalDuration& loopTimeoutDuration) const {
-    return kPreparedModel->createReusableExecution(request, measure, loopTimeoutDuration);
+        const nn::OptionalDuration& loopTimeoutDuration,
+        const std::vector<nn::TokenValuePair>& hints,
+        const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const {
+    return kPreparedModel->createReusableExecution(request, measure, loopTimeoutDuration, hints,
+                                                   extensionNameToPrefix);
 }
 
 }  // namespace android::hardware::neuralnetworks::V1_0::utils
diff --git a/neuralnetworks/1.0/utils/src/Callbacks.cpp b/neuralnetworks/1.0/utils/src/Callbacks.cpp
index ea3ea56..7b478ae 100644
--- a/neuralnetworks/1.0/utils/src/Callbacks.cpp
+++ b/neuralnetworks/1.0/utils/src/Callbacks.cpp
@@ -17,7 +17,9 @@
 #include "Callbacks.h"
 
 #include "Conversions.h"
+#include "HandleError.h"
 #include "PreparedModel.h"
+#include "ProtectCallback.h"
 #include "Utils.h"
 
 #include <android/hardware/neuralnetworks/1.0/IExecutionCallback.h>
@@ -27,8 +29,6 @@
 #include <nnapi/Result.h>
 #include <nnapi/Types.h>
 #include <nnapi/hal/CommonUtils.h>
-#include <nnapi/hal/HandleError.h>
-#include <nnapi/hal/ProtectCallback.h>
 #include <nnapi/hal/TransferValue.h>
 
 #include <utility>
@@ -40,19 +40,19 @@
 
 nn::GeneralResult<std::vector<bool>> supportedOperationsCallback(
         ErrorStatus status, const hidl_vec<bool>& supportedOperations) {
-    HANDLE_HAL_STATUS(status) << "get supported operations failed with " << toString(status);
+    HANDLE_STATUS_HIDL(status) << "get supported operations failed with " << toString(status);
     return supportedOperations;
 }
 
 nn::GeneralResult<nn::SharedPreparedModel> prepareModelCallback(
         ErrorStatus status, const sp<IPreparedModel>& preparedModel) {
-    HANDLE_HAL_STATUS(status) << "model preparation failed with " << toString(status);
+    HANDLE_STATUS_HIDL(status) << "model preparation failed with " << toString(status);
     return NN_TRY(PreparedModel::create(preparedModel));
 }
 
 nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> executionCallback(
         ErrorStatus status) {
-    HANDLE_HAL_STATUS(status) << "execution failed with " << toString(status);
+    HANDLE_STATUS_HIDL(status) << "execution failed with " << toString(status);
     return {};
 }
 
diff --git a/neuralnetworks/1.0/utils/src/Conversions.cpp b/neuralnetworks/1.0/utils/src/Conversions.cpp
index c0498eb..d98fef0 100644
--- a/neuralnetworks/1.0/utils/src/Conversions.cpp
+++ b/neuralnetworks/1.0/utils/src/Conversions.cpp
@@ -37,6 +37,11 @@
 
 #include "Utils.h"
 
+#ifdef __ANDROID__
+#include <android/hardware_buffer.h>
+#include <vndk/hardware_buffer.h>
+#endif  // __ANDROID__
+
 namespace {
 
 template <typename Type>
@@ -49,6 +54,7 @@
 namespace android::nn {
 namespace {
 
+using hardware::hidl_handle;
 using hardware::hidl_memory;
 using hardware::hidl_vec;
 
@@ -74,6 +80,123 @@
     return canonical;
 }
 
+nn::GeneralResult<nn::Memory::Unknown::Handle> unknownHandleFromNativeHandle(
+        const native_handle_t* handle) {
+    if (handle == nullptr) {
+        return NN_ERROR() << "unknownHandleFromNativeHandle failed because handle is nullptr";
+    }
+
+    std::vector<base::unique_fd> fds =
+            NN_TRY(nn::dupFds(handle->data + 0, handle->data + handle->numFds));
+
+    std::vector<int> ints(handle->data + handle->numFds,
+                          handle->data + handle->numFds + handle->numInts);
+
+    return nn::Memory::Unknown::Handle{.fds = std::move(fds), .ints = std::move(ints)};
+}
+
+nn::GeneralResult<nn::SharedMemory> createSharedMemoryFromHidlMemory(const hidl_memory& memory) {
+    CHECK_LE(memory.size(), std::numeric_limits<size_t>::max());
+    if (!memory.valid()) {
+        return NN_ERROR() << "Unable to convert invalid hidl_memory";
+    }
+
+    if (memory.name() == "ashmem") {
+        if (memory.handle()->numFds != 1) {
+            return NN_ERROR() << "Unable to convert invalid ashmem memory object with "
+                              << memory.handle()->numFds << " numFds, but expected 1";
+        }
+        if (memory.handle()->numInts != 0) {
+            return NN_ERROR() << "Unable to convert invalid ashmem memory object with "
+                              << memory.handle()->numInts << " numInts, but expected 0";
+        }
+        auto fd = NN_TRY(nn::dupFd(memory.handle()->data[0]));
+        auto handle = nn::Memory::Ashmem{
+                .fd = std::move(fd),
+                .size = static_cast<size_t>(memory.size()),
+        };
+        return std::make_shared<const nn::Memory>(nn::Memory{.handle = std::move(handle)});
+    }
+
+    if (memory.name() == "mmap_fd") {
+        if (memory.handle()->numFds != 1) {
+            return NN_ERROR() << "Unable to convert invalid mmap_fd memory object with "
+                              << memory.handle()->numFds << " numFds, but expected 1";
+        }
+        if (memory.handle()->numInts != 3) {
+            return NN_ERROR() << "Unable to convert invalid mmap_fd memory object with "
+                              << memory.handle()->numInts << " numInts, but expected 3";
+        }
+
+        const int fd = memory.handle()->data[0];
+        const int prot = memory.handle()->data[1];
+        const int lower = memory.handle()->data[2];
+        const int higher = memory.handle()->data[3];
+        const size_t offset = nn::getOffsetFromInts(lower, higher);
+
+        return nn::createSharedMemoryFromFd(static_cast<size_t>(memory.size()), prot, fd, offset);
+    }
+
+    if (memory.name() != "hardware_buffer_blob") {
+        auto handle = NN_TRY(unknownHandleFromNativeHandle(memory.handle()));
+        auto unknown = nn::Memory::Unknown{
+                .handle = std::move(handle),
+                .size = static_cast<size_t>(memory.size()),
+                .name = memory.name(),
+        };
+        return std::make_shared<const nn::Memory>(nn::Memory{.handle = std::move(unknown)});
+    }
+
+#ifdef __ANDROID__
+    constexpr auto roundUpToMultiple = [](uint32_t value, uint32_t multiple) -> uint32_t {
+        return (value + multiple - 1) / multiple * multiple;
+    };
+
+    const auto size = memory.size();
+    const auto format = AHARDWAREBUFFER_FORMAT_BLOB;
+    const auto usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
+    const uint32_t width = size;
+    const uint32_t height = 1;  // height is always 1 for BLOB mode AHardwareBuffer.
+    const uint32_t layers = 1;  // layers is always 1 for BLOB mode AHardwareBuffer.
+
+    // AHardwareBuffer_createFromHandle() might fail because an allocator
+    // expects a specific stride value. In that case, we try to guess it by
+    // aligning the width to small powers of 2.
+    // TODO(b/174120849): Avoid stride assumptions.
+    AHardwareBuffer* hardwareBuffer = nullptr;
+    status_t status = UNKNOWN_ERROR;
+    for (uint32_t alignment : {1, 4, 32, 64, 128, 2, 8, 16}) {
+        const uint32_t stride = roundUpToMultiple(width, alignment);
+        AHardwareBuffer_Desc desc{
+                .width = width,
+                .height = height,
+                .layers = layers,
+                .format = format,
+                .usage = usage,
+                .stride = stride,
+        };
+        status = AHardwareBuffer_createFromHandle(&desc, memory.handle(),
+                                                  AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_CLONE,
+                                                  &hardwareBuffer);
+        if (status == NO_ERROR) {
+            break;
+        }
+    }
+    if (status != NO_ERROR) {
+        return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+               << "Can't create AHardwareBuffer from handle. Error: " << status;
+    }
+
+    return nn::createSharedMemoryFromAHWB(hardwareBuffer, /*takeOwnership=*/true);
+#else   // __ANDROID__
+    LOG(FATAL) << "nn::GeneralResult<nn::SharedMemory> createSharedMemoryFromHidlMemory(const "
+                  "hidl_memory& memory): Not Available on Host Build";
+    return (NN_ERROR() << "createSharedMemoryFromHidlMemory failed")
+            .
+            operator nn::GeneralResult<nn::SharedMemory>();
+#endif  // __ANDROID__
+}
+
 }  // anonymous namespace
 
 GeneralResult<OperandType> unvalidatedConvert(const hal::V1_0::OperandType& operandType) {
@@ -124,19 +247,23 @@
 }
 
 GeneralResult<Operand> unvalidatedConvert(const hal::V1_0::Operand& operand) {
+    const auto type = NN_TRY(unvalidatedConvert(operand.type));
+    const auto lifetime = NN_TRY(unvalidatedConvert(operand.lifetime));
+    const auto location = NN_TRY(unvalidatedConvert(operand.location));
     return Operand{
-            .type = NN_TRY(unvalidatedConvert(operand.type)),
+            .type = type,
             .dimensions = operand.dimensions,
             .scale = operand.scale,
             .zeroPoint = operand.zeroPoint,
-            .lifetime = NN_TRY(unvalidatedConvert(operand.lifetime)),
-            .location = NN_TRY(unvalidatedConvert(operand.location)),
+            .lifetime = lifetime,
+            .location = location,
     };
 }
 
 GeneralResult<Operation> unvalidatedConvert(const hal::V1_0::Operation& operation) {
+    const auto type = NN_TRY(unvalidatedConvert(operation.type));
     return Operation{
-            .type = NN_TRY(unvalidatedConvert(operation.type)),
+            .type = type,
             .inputs = operation.inputs,
             .outputs = operation.outputs,
     };
@@ -146,8 +273,20 @@
     return Model::OperandValues(operandValues.data(), operandValues.size());
 }
 
+GeneralResult<SharedHandle> unvalidatedConvert(const hidl_handle& handle) {
+    if (handle.getNativeHandle() == nullptr) {
+        return nullptr;
+    }
+    if (handle->numFds != 1 || handle->numInts != 0) {
+        return NN_ERROR()
+               << "unvalidatedConvert failed because handle does not only hold a single fd";
+    }
+    auto duplicatedFd = NN_TRY(nn::dupFd(handle->data[0]));
+    return std::make_shared<const Handle>(std::move(duplicatedFd));
+}
+
 GeneralResult<SharedMemory> unvalidatedConvert(const hidl_memory& memory) {
-    return hal::utils::createSharedMemoryFromHidlMemory(memory);
+    return createSharedMemoryFromHidlMemory(memory);
 }
 
 GeneralResult<Model> unvalidatedConvert(const hal::V1_0::Model& model) {
@@ -155,7 +294,7 @@
 
     // Verify number of consumers.
     const auto numberOfConsumers =
-            NN_TRY(hal::utils::countNumberOfConsumers(model.operands.size(), operations));
+            NN_TRY(countNumberOfConsumers(model.operands.size(), operations));
     CHECK(model.operands.size() == numberOfConsumers.size());
     for (size_t i = 0; i < model.operands.size(); ++i) {
         if (model.operands[i].numberOfConsumers != numberOfConsumers[i]) {
@@ -165,26 +304,30 @@
         }
     }
 
+    auto operands = NN_TRY(unvalidatedConvert(model.operands));
     auto main = Model::Subgraph{
-            .operands = NN_TRY(unvalidatedConvert(model.operands)),
+            .operands = std::move(operands),
             .operations = std::move(operations),
             .inputIndexes = model.inputIndexes,
             .outputIndexes = model.outputIndexes,
     };
 
+    auto operandValues = NN_TRY(unvalidatedConvert(model.operandValues));
+    auto pools = NN_TRY(unvalidatedConvert(model.pools));
     return Model{
             .main = std::move(main),
-            .operandValues = NN_TRY(unvalidatedConvert(model.operandValues)),
-            .pools = NN_TRY(unvalidatedConvert(model.pools)),
+            .operandValues = std::move(operandValues),
+            .pools = std::move(pools),
     };
 }
 
 GeneralResult<Request::Argument> unvalidatedConvert(const hal::V1_0::RequestArgument& argument) {
     const auto lifetime = argument.hasNoValue ? Request::Argument::LifeTime::NO_VALUE
                                               : Request::Argument::LifeTime::POOL;
+    const auto location = NN_TRY(unvalidatedConvert(argument.location));
     return Request::Argument{
             .lifetime = lifetime,
-            .location = NN_TRY(unvalidatedConvert(argument.location)),
+            .location = location,
             .dimensions = argument.dimensions,
     };
 }
@@ -195,9 +338,11 @@
     pools.reserve(memories.size());
     std::move(memories.begin(), memories.end(), std::back_inserter(pools));
 
+    auto inputs = NN_TRY(unvalidatedConvert(request.inputs));
+    auto outputs = NN_TRY(unvalidatedConvert(request.outputs));
     return Request{
-            .inputs = NN_TRY(unvalidatedConvert(request.inputs)),
-            .outputs = NN_TRY(unvalidatedConvert(request.outputs)),
+            .inputs = std::move(inputs),
+            .outputs = std::move(outputs),
             .pools = std::move(pools),
     };
 }
@@ -260,6 +405,82 @@
     return utils::unvalidatedConvert(canonical);
 }
 
+nn::GeneralResult<hidl_handle> createNativeHandleFrom(std::vector<base::unique_fd> fds,
+                                                      const std::vector<int32_t>& ints) {
+    constexpr size_t kIntMax = std::numeric_limits<int>::max();
+    CHECK_LE(fds.size(), kIntMax);
+    CHECK_LE(ints.size(), kIntMax);
+    native_handle_t* nativeHandle =
+            native_handle_create(static_cast<int>(fds.size()), static_cast<int>(ints.size()));
+    if (nativeHandle == nullptr) {
+        return NN_ERROR() << "Failed to create native_handle";
+    }
+
+    for (size_t i = 0; i < fds.size(); ++i) {
+        nativeHandle->data[i] = fds[i].release();
+    }
+    std::copy(ints.begin(), ints.end(), nativeHandle->data + nativeHandle->numFds);
+
+    hidl_handle handle;
+    handle.setTo(nativeHandle, /*shouldOwn=*/true);
+    return handle;
+}
+
+nn::GeneralResult<hidl_handle> createNativeHandleFrom(base::unique_fd fd,
+                                                      const std::vector<int32_t>& ints) {
+    std::vector<base::unique_fd> fds;
+    fds.push_back(std::move(fd));
+    return createNativeHandleFrom(std::move(fds), ints);
+}
+
+nn::GeneralResult<hidl_handle> createNativeHandleFrom(const nn::Memory::Unknown::Handle& handle) {
+    std::vector<base::unique_fd> fds = NN_TRY(nn::dupFds(handle.fds.begin(), handle.fds.end()));
+    return createNativeHandleFrom(std::move(fds), handle.ints);
+}
+
+nn::GeneralResult<hidl_memory> createHidlMemoryFrom(const nn::Memory::Ashmem& memory) {
+    auto fd = NN_TRY(nn::dupFd(memory.fd));
+    auto handle = NN_TRY(createNativeHandleFrom(std::move(fd), {}));
+    return hidl_memory("ashmem", std::move(handle), memory.size);
+}
+
+nn::GeneralResult<hidl_memory> createHidlMemoryFrom(const nn::Memory::Fd& memory) {
+    auto fd = NN_TRY(nn::dupFd(memory.fd));
+
+    const auto [lowOffsetBits, highOffsetBits] = nn::getIntsFromOffset(memory.offset);
+    const std::vector<int> ints = {memory.prot, lowOffsetBits, highOffsetBits};
+
+    auto handle = NN_TRY(createNativeHandleFrom(std::move(fd), ints));
+    return hidl_memory("mmap_fd", std::move(handle), memory.size);
+}
+
+nn::GeneralResult<hidl_memory> createHidlMemoryFrom(const nn::Memory::HardwareBuffer& memory) {
+#ifdef __ANDROID__
+    const auto* ahwb = memory.handle.get();
+    AHardwareBuffer_Desc bufferDesc;
+    AHardwareBuffer_describe(ahwb, &bufferDesc);
+
+    const bool isBlob = bufferDesc.format == AHARDWAREBUFFER_FORMAT_BLOB;
+    const size_t size = isBlob ? bufferDesc.width : 0;
+    const char* const name = isBlob ? "hardware_buffer_blob" : "hardware_buffer";
+
+    const native_handle_t* nativeHandle = AHardwareBuffer_getNativeHandle(ahwb);
+    const hidl_handle hidlHandle(nativeHandle);
+    hidl_handle copiedHandle(hidlHandle);
+
+    return hidl_memory(name, std::move(copiedHandle), size);
+#else   // __ANDROID__
+    LOG(FATAL) << "nn::GeneralResult<hidl_memory> createHidlMemoryFrom(const "
+                  "nn::Memory::HardwareBuffer& memory): Not Available on Host Build";
+    (void)memory;
+    return (NN_ERROR() << "createHidlMemoryFrom failed").operator nn::GeneralResult<hidl_memory>();
+#endif  // __ANDROID__
+}
+
+nn::GeneralResult<hidl_memory> createHidlMemoryFrom(const nn::Memory::Unknown& memory) {
+    return hidl_memory(memory.name, NN_TRY(createNativeHandleFrom(memory.handle)), memory.size);
+}
+
 }  // anonymous namespace
 
 nn::GeneralResult<OperandType> unvalidatedConvert(const nn::OperandType& operandType) {
@@ -291,11 +512,13 @@
 }
 
 nn::GeneralResult<Capabilities> unvalidatedConvert(const nn::Capabilities& capabilities) {
+    const auto float32Performance = NN_TRY(unvalidatedConvert(
+            capabilities.operandPerformance.lookup(nn::OperandType::TENSOR_FLOAT32)));
+    const auto quantized8Performance = NN_TRY(unvalidatedConvert(
+            capabilities.operandPerformance.lookup(nn::OperandType::TENSOR_QUANT8_ASYMM)));
     return Capabilities{
-            .float32Performance = NN_TRY(unvalidatedConvert(
-                    capabilities.operandPerformance.lookup(nn::OperandType::TENSOR_FLOAT32))),
-            .quantized8Performance = NN_TRY(unvalidatedConvert(
-                    capabilities.operandPerformance.lookup(nn::OperandType::TENSOR_QUANT8_ASYMM))),
+            .float32Performance = float32Performance,
+            .quantized8Performance = quantized8Performance,
     };
 }
 
@@ -308,20 +531,24 @@
 }
 
 nn::GeneralResult<Operand> unvalidatedConvert(const nn::Operand& operand) {
+    const auto type = NN_TRY(unvalidatedConvert(operand.type));
+    const auto lifetime = NN_TRY(unvalidatedConvert(operand.lifetime));
+    const auto location = NN_TRY(unvalidatedConvert(operand.location));
     return Operand{
-            .type = NN_TRY(unvalidatedConvert(operand.type)),
+            .type = type,
             .dimensions = operand.dimensions,
             .numberOfConsumers = 0,
             .scale = operand.scale,
             .zeroPoint = operand.zeroPoint,
-            .lifetime = NN_TRY(unvalidatedConvert(operand.lifetime)),
-            .location = NN_TRY(unvalidatedConvert(operand.location)),
+            .lifetime = lifetime,
+            .location = location,
     };
 }
 
 nn::GeneralResult<Operation> unvalidatedConvert(const nn::Operation& operation) {
+    const auto type = NN_TRY(unvalidatedConvert(operation.type));
     return Operation{
-            .type = NN_TRY(unvalidatedConvert(operation.type)),
+            .type = type,
             .inputs = operation.inputs,
             .outputs = operation.outputs,
     };
@@ -332,8 +559,19 @@
     return hidl_vec<uint8_t>(operandValues.data(), operandValues.data() + operandValues.size());
 }
 
+nn::GeneralResult<hidl_handle> unvalidatedConvert(const nn::SharedHandle& handle) {
+    if (handle == nullptr) {
+        return {};
+    }
+    base::unique_fd fd = NN_TRY(nn::dupFd(handle->get()));
+    return createNativeHandleFrom(std::move(fd), {});
+}
+
 nn::GeneralResult<hidl_memory> unvalidatedConvert(const nn::SharedMemory& memory) {
-    return hal::utils::createHidlMemoryFromSharedMemory(memory);
+    if (memory == nullptr) {
+        return NN_ERROR() << "Memory must be non-empty";
+    }
+    return std::visit([](const auto& x) { return createHidlMemoryFrom(x); }, memory->handle);
 }
 
 nn::GeneralResult<Model> unvalidatedConvert(const nn::Model& model) {
@@ -346,19 +584,22 @@
 
     // Update number of consumers.
     const auto numberOfConsumers =
-            NN_TRY(hal::utils::countNumberOfConsumers(operands.size(), model.main.operations));
+            NN_TRY(countNumberOfConsumers(operands.size(), model.main.operations));
     CHECK(operands.size() == numberOfConsumers.size());
     for (size_t i = 0; i < operands.size(); ++i) {
         operands[i].numberOfConsumers = numberOfConsumers[i];
     }
 
+    auto operations = NN_TRY(unvalidatedConvert(model.main.operations));
+    auto operandValues = NN_TRY(unvalidatedConvert(model.operandValues));
+    auto pools = NN_TRY(unvalidatedConvert(model.pools));
     return Model{
             .operands = std::move(operands),
-            .operations = NN_TRY(unvalidatedConvert(model.main.operations)),
+            .operations = std::move(operations),
             .inputIndexes = model.main.inputIndexes,
             .outputIndexes = model.main.outputIndexes,
-            .operandValues = NN_TRY(unvalidatedConvert(model.operandValues)),
-            .pools = NN_TRY(unvalidatedConvert(model.pools)),
+            .operandValues = std::move(operandValues),
+            .pools = std::move(pools),
     };
 }
 
@@ -369,9 +610,10 @@
                << "Request cannot be unvalidatedConverted because it contains pointer-based memory";
     }
     const bool hasNoValue = requestArgument.lifetime == nn::Request::Argument::LifeTime::NO_VALUE;
+    const auto location = NN_TRY(unvalidatedConvert(requestArgument.location));
     return RequestArgument{
             .hasNoValue = hasNoValue,
-            .location = NN_TRY(unvalidatedConvert(requestArgument.location)),
+            .location = location,
             .dimensions = requestArgument.dimensions,
     };
 }
@@ -386,10 +628,13 @@
                << "Request cannot be unvalidatedConverted because it contains pointer-based memory";
     }
 
+    auto inputs = NN_TRY(unvalidatedConvert(request.inputs));
+    auto outputs = NN_TRY(unvalidatedConvert(request.outputs));
+    auto pools = NN_TRY(unvalidatedConvert(request.pools));
     return Request{
-            .inputs = NN_TRY(unvalidatedConvert(request.inputs)),
-            .outputs = NN_TRY(unvalidatedConvert(request.outputs)),
-            .pools = NN_TRY(unvalidatedConvert(request.pools)),
+            .inputs = std::move(inputs),
+            .outputs = std::move(outputs),
+            .pools = std::move(pools),
     };
 }
 
diff --git a/neuralnetworks/1.0/utils/src/Device.cpp b/neuralnetworks/1.0/utils/src/Device.cpp
index 93bd81a..620d040 100644
--- a/neuralnetworks/1.0/utils/src/Device.cpp
+++ b/neuralnetworks/1.0/utils/src/Device.cpp
@@ -18,6 +18,8 @@
 
 #include "Callbacks.h"
 #include "Conversions.h"
+#include "HandleError.h"
+#include "ProtectCallback.h"
 #include "Utils.h"
 
 #include <android/hardware/neuralnetworks/1.0/IDevice.h>
@@ -29,8 +31,6 @@
 #include <nnapi/Result.h>
 #include <nnapi/Types.h>
 #include <nnapi/hal/CommonUtils.h>
-#include <nnapi/hal/HandleError.h>
-#include <nnapi/hal/ProtectCallback.h>
 #include <nnapi/hal/TransferValue.h>
 
 #include <functional>
@@ -47,7 +47,7 @@
 
 nn::GeneralResult<nn::Capabilities> capabilitiesCallback(ErrorStatus status,
                                                          const Capabilities& capabilities) {
-    HANDLE_HAL_STATUS(status) << "getting capabilities failed with " << toString(status);
+    HANDLE_STATUS_HIDL(status) << "getting capabilities failed with " << toString(status);
     return nn::convert(capabilities);
 }
 
@@ -99,7 +99,7 @@
 }
 
 nn::Version Device::getFeatureLevel() const {
-    return nn::Version::ANDROID_OC_MR1;
+    return kVersion;
 }
 
 nn::DeviceType Device::getType() const {
@@ -143,7 +143,9 @@
 nn::GeneralResult<nn::SharedPreparedModel> Device::prepareModel(
         const nn::Model& model, nn::ExecutionPreference /*preference*/, nn::Priority /*priority*/,
         nn::OptionalTimePoint /*deadline*/, const std::vector<nn::SharedHandle>& /*modelCache*/,
-        const std::vector<nn::SharedHandle>& /*dataCache*/, const nn::CacheToken& /*token*/) const {
+        const std::vector<nn::SharedHandle>& /*dataCache*/, const nn::CacheToken& /*token*/,
+        const std::vector<nn::TokenValuePair>& /*hints*/,
+        const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
     // Ensure that model is ready for IPC.
     std::optional<nn::Model> maybeModelInShared;
     const nn::Model& modelInShared =
@@ -156,7 +158,7 @@
 
     const auto ret = kDevice->prepareModel(hidlModel, cb);
     const auto status = HANDLE_TRANSPORT_FAILURE(ret);
-    HANDLE_HAL_STATUS(status) << "model preparation failed with " << toString(status);
+    HANDLE_STATUS_HIDL(status) << "model preparation failed with " << toString(status);
 
     return cb->get();
 }
diff --git a/neuralnetworks/1.0/utils/src/Execution.cpp b/neuralnetworks/1.0/utils/src/Execution.cpp
index 7a3216b..6e105a6 100644
--- a/neuralnetworks/1.0/utils/src/Execution.cpp
+++ b/neuralnetworks/1.0/utils/src/Execution.cpp
@@ -18,6 +18,8 @@
 
 #include "Callbacks.h"
 #include "Conversions.h"
+#include "HandleError.h"
+#include "ProtectCallback.h"
 #include "Utils.h"
 
 #include <android/hardware/neuralnetworks/1.0/IPreparedModel.h>
@@ -27,8 +29,6 @@
 #include <nnapi/TypeUtils.h>
 #include <nnapi/Types.h>
 #include <nnapi/hal/CommonUtils.h>
-#include <nnapi/hal/HandleError.h>
-#include <nnapi/hal/ProtectCallback.h>
 
 #include <memory>
 #include <utility>
diff --git a/neuralnetworks/1.0/utils/src/PreparedModel.cpp b/neuralnetworks/1.0/utils/src/PreparedModel.cpp
index 00970c0..b8055fc 100644
--- a/neuralnetworks/1.0/utils/src/PreparedModel.cpp
+++ b/neuralnetworks/1.0/utils/src/PreparedModel.cpp
@@ -20,6 +20,8 @@
 #include "Callbacks.h"
 #include "Conversions.h"
 #include "Execution.h"
+#include "HandleError.h"
+#include "ProtectCallback.h"
 #include "Utils.h"
 
 #include <android/hardware/neuralnetworks/1.0/IPreparedModel.h>
@@ -28,8 +30,6 @@
 #include <nnapi/Result.h>
 #include <nnapi/Types.h>
 #include <nnapi/hal/CommonUtils.h>
-#include <nnapi/hal/HandleError.h>
-#include <nnapi/hal/ProtectCallback.h>
 
 #include <memory>
 #include <tuple>
@@ -59,16 +59,17 @@
 nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> PreparedModel::execute(
         const nn::Request& request, nn::MeasureTiming /*measure*/,
         const nn::OptionalTimePoint& /*deadline*/,
-        const nn::OptionalDuration& /*loopTimeoutDuration*/) const {
+        const nn::OptionalDuration& /*loopTimeoutDuration*/,
+        const std::vector<nn::TokenValuePair>& /*hints*/,
+        const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
     // Ensure that request is ready for IPC.
     std::optional<nn::Request> maybeRequestInShared;
     hal::utils::RequestRelocation relocation;
-    const nn::Request& requestInShared =
-            NN_TRY(hal::utils::makeExecutionFailure(hal::utils::convertRequestFromPointerToShared(
-                    &request, nn::kDefaultRequestMemoryAlignment, nn::kMinMemoryPadding,
-                    &maybeRequestInShared, &relocation)));
+    const nn::Request& requestInShared = NN_TRY(hal::utils::convertRequestFromPointerToShared(
+            &request, nn::kDefaultRequestMemoryAlignment, nn::kMinMemoryPadding,
+            &maybeRequestInShared, &relocation));
 
-    const auto hidlRequest = NN_TRY(hal::utils::makeExecutionFailure(convert(requestInShared)));
+    const auto hidlRequest = NN_TRY(convert(requestInShared));
 
     return executeInternal(hidlRequest, relocation);
 }
@@ -85,7 +86,7 @@
 
     const auto ret = kPreparedModel->execute(request, cb);
     const auto status = HANDLE_TRANSPORT_FAILURE(ret);
-    HANDLE_HAL_STATUS(status) << "execution failed with " << toString(status);
+    HANDLE_STATUS_HIDL(status) << "execution failed with " << toString(status);
 
     auto result = NN_TRY(cb->get());
     if (relocation.output) {
@@ -95,19 +96,22 @@
 }
 
 nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>>
-PreparedModel::executeFenced(const nn::Request& /*request*/,
-                             const std::vector<nn::SyncFence>& /*waitFor*/,
-                             nn::MeasureTiming /*measure*/,
-                             const nn::OptionalTimePoint& /*deadline*/,
-                             const nn::OptionalDuration& /*loopTimeoutDuration*/,
-                             const nn::OptionalDuration& /*timeoutDurationAfterFence*/) const {
+PreparedModel::executeFenced(
+        const nn::Request& /*request*/, const std::vector<nn::SyncFence>& /*waitFor*/,
+        nn::MeasureTiming /*measure*/, const nn::OptionalTimePoint& /*deadline*/,
+        const nn::OptionalDuration& /*loopTimeoutDuration*/,
+        const nn::OptionalDuration& /*timeoutDurationAfterFence*/,
+        const std::vector<nn::TokenValuePair>& /*hints*/,
+        const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
     return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
            << "IPreparedModel::executeFenced is not supported on 1.0 HAL service";
 }
 
 nn::GeneralResult<nn::SharedExecution> PreparedModel::createReusableExecution(
         const nn::Request& request, nn::MeasureTiming /*measure*/,
-        const nn::OptionalDuration& /*loopTimeoutDuration*/) const {
+        const nn::OptionalDuration& /*loopTimeoutDuration*/,
+        const std::vector<nn::TokenValuePair>& /*hints*/,
+        const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
     // Ensure that request is ready for IPC.
     std::optional<nn::Request> maybeRequestInShared;
     hal::utils::RequestRelocation relocation;
diff --git a/neuralnetworks/1.0/utils/src/ProtectCallback.cpp b/neuralnetworks/1.0/utils/src/ProtectCallback.cpp
new file mode 100644
index 0000000..89539b5
--- /dev/null
+++ b/neuralnetworks/1.0/utils/src/ProtectCallback.cpp
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "ProtectCallback.h"
+
+#include <android-base/logging.h>
+#include <android-base/scopeguard.h>
+#include <android-base/thread_annotations.h>
+#include <android/hidl/base/1.0/IBase.h>
+#include <hidl/HidlSupport.h>
+#include <nnapi/Result.h>
+
+#include "HandleError.h"
+
+#include <algorithm>
+#include <functional>
+#include <mutex>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::utils {
+
+void DeathRecipient::serviceDied(uint64_t /*cookie*/, const wp<hidl::base::V1_0::IBase>& /*who*/) {
+    std::lock_guard guard(mMutex);
+    std::for_each(mObjects.begin(), mObjects.end(),
+                  [](IProtectedCallback* killable) { killable->notifyAsDeadObject(); });
+    mObjects.clear();
+    mIsDeadObject = true;
+}
+
+void DeathRecipient::add(IProtectedCallback* killable) const {
+    CHECK(killable != nullptr);
+    std::lock_guard guard(mMutex);
+    if (mIsDeadObject) {
+        killable->notifyAsDeadObject();
+    } else {
+        mObjects.push_back(killable);
+    }
+}
+
+void DeathRecipient::remove(IProtectedCallback* killable) const {
+    CHECK(killable != nullptr);
+    std::lock_guard guard(mMutex);
+    const auto newEnd = std::remove(mObjects.begin(), mObjects.end(), killable);
+    mObjects.erase(newEnd, mObjects.end());
+}
+
+nn::GeneralResult<DeathHandler> DeathHandler::create(sp<hidl::base::V1_0::IBase> object) {
+    if (object == nullptr) {
+        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
+               << "utils::DeathHandler::create must have non-null object";
+    }
+    auto deathRecipient = sp<DeathRecipient>::make();
+
+    const auto ret = object->linkToDeath(deathRecipient, /*cookie=*/0);
+    const bool success = HANDLE_TRANSPORT_FAILURE(ret);
+    if (!success) {
+        return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "IBase::linkToDeath returned false";
+    }
+
+    return DeathHandler(std::move(object), std::move(deathRecipient));
+}
+
+DeathHandler::DeathHandler(sp<hidl::base::V1_0::IBase> object, sp<DeathRecipient> deathRecipient)
+    : mObject(std::move(object)), mDeathRecipient(std::move(deathRecipient)) {
+    CHECK(mObject != nullptr);
+    CHECK(mDeathRecipient != nullptr);
+}
+
+DeathHandler::~DeathHandler() {
+    if (mObject != nullptr && mDeathRecipient != nullptr) {
+        const auto successful = mObject->unlinkToDeath(mDeathRecipient).isOk();
+        if (!successful) {
+            LOG(ERROR) << "IBase::linkToDeath failed";
+        }
+    }
+}
+
+[[nodiscard]] base::ScopeGuard<DeathHandler::Cleanup> DeathHandler::protectCallback(
+        IProtectedCallback* killable) const {
+    CHECK(killable != nullptr);
+    mDeathRecipient->add(killable);
+    return base::make_scope_guard(
+            [deathRecipient = mDeathRecipient, killable] { deathRecipient->remove(killable); });
+}
+
+void DeathHandler::protectCallbackForLifetimeOfDeathHandler(IProtectedCallback* killable) const {
+    CHECK(killable != nullptr);
+    mDeathRecipient->add(killable);
+}
+
+}  // namespace android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/1.0/utils/test/DeviceTest.cpp b/neuralnetworks/1.0/utils/test/DeviceTest.cpp
index e881da2..9e9db16 100644
--- a/neuralnetworks/1.0/utils/test/DeviceTest.cpp
+++ b/neuralnetworks/1.0/utils/test/DeviceTest.cpp
@@ -233,7 +233,7 @@
     const auto featureLevel = device->getFeatureLevel();
 
     // verify result
-    EXPECT_EQ(featureLevel, nn::Version::ANDROID_OC_MR1);
+    EXPECT_EQ(featureLevel, nn::kVersionFeatureLevel1);
 }
 
 TEST(DeviceTest, getCachedData) {
@@ -380,7 +380,7 @@
 
     // run test
     const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
-                                             nn::Priority::DEFAULT, {}, {}, {}, {});
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_TRUE(result.has_value())
@@ -399,7 +399,7 @@
 
     // run test
     const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
-                                             nn::Priority::DEFAULT, {}, {}, {}, {});
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -417,7 +417,7 @@
 
     // run test
     const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
-                                             nn::Priority::DEFAULT, {}, {}, {}, {});
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -435,7 +435,7 @@
 
     // run test
     const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
-                                             nn::Priority::DEFAULT, {}, {}, {}, {});
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -452,7 +452,7 @@
 
     // run test
     const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
-                                             nn::Priority::DEFAULT, {}, {}, {}, {});
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -469,7 +469,7 @@
 
     // run test
     const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
-                                             nn::Priority::DEFAULT, {}, {}, {}, {});
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -488,7 +488,7 @@
 
     // run test
     const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
-                                             nn::Priority::DEFAULT, {}, {}, {}, {});
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
diff --git a/neuralnetworks/1.0/utils/test/PreparedModelTest.cpp b/neuralnetworks/1.0/utils/test/PreparedModelTest.cpp
index 7820c06..e03a98d 100644
--- a/neuralnetworks/1.0/utils/test/PreparedModelTest.cpp
+++ b/neuralnetworks/1.0/utils/test/PreparedModelTest.cpp
@@ -121,7 +121,7 @@
             .WillOnce(Invoke(makeExecute(V1_0::ErrorStatus::NONE, V1_0::ErrorStatus::NONE)));
 
     // run test
-    const auto result = preparedModel->execute({}, {}, {}, {});
+    const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
 
     // verify result
     EXPECT_TRUE(result.has_value())
@@ -138,7 +138,7 @@
                                          V1_0::ErrorStatus::GENERAL_FAILURE)));
 
     // run test
-    const auto result = preparedModel->execute({}, {}, {}, {});
+    const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -155,7 +155,7 @@
                     makeExecute(V1_0::ErrorStatus::NONE, V1_0::ErrorStatus::GENERAL_FAILURE)));
 
     // run test
-    const auto result = preparedModel->execute({}, {}, {}, {});
+    const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -171,7 +171,7 @@
             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
 
     // run test
-    const auto result = preparedModel->execute({}, {}, {}, {});
+    const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -187,7 +187,7 @@
             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
 
     // run test
-    const auto result = preparedModel->execute({}, {}, {}, {});
+    const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -205,7 +205,7 @@
     EXPECT_CALL(*mockPreparedModel, execute(_, _)).Times(1).WillOnce(InvokeWithoutArgs(ret));
 
     // run test
-    const auto result = preparedModel->execute({}, {}, {}, {});
+    const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -218,7 +218,7 @@
     const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
 
     // run test
-    const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
+    const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -235,7 +235,7 @@
             .WillRepeatedly(Invoke(makeExecute(V1_0::ErrorStatus::NONE, V1_0::ErrorStatus::NONE)));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -258,7 +258,7 @@
                                          V1_0::ErrorStatus::GENERAL_FAILURE)));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -279,7 +279,7 @@
                     makeExecute(V1_0::ErrorStatus::NONE, V1_0::ErrorStatus::GENERAL_FAILURE)));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -299,7 +299,7 @@
             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -319,7 +319,7 @@
             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -341,7 +341,7 @@
     EXPECT_CALL(*mockPreparedModel, execute(_, _)).Times(1).WillOnce(InvokeWithoutArgs(ret));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -358,7 +358,7 @@
     const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
diff --git a/neuralnetworks/1.0/vts/OWNERS b/neuralnetworks/1.0/vts/OWNERS
deleted file mode 100644
index b5a8e1f..0000000
--- a/neuralnetworks/1.0/vts/OWNERS
+++ /dev/null
@@ -1,16 +0,0 @@
-# Neuralnetworks team
-butlermichael@google.com
-dgross@google.com
-jeanluc@google.com
-levp@google.com
-miaowang@google.com
-mikie@google.com
-mks@google.com
-pszczepaniak@google.com
-slavash@google.com
-vddang@google.com
-xusongw@google.com
-
-# VTS team
-yim@google.com
-yuexima@google.com
diff --git a/neuralnetworks/1.0/vts/functional/Android.bp b/neuralnetworks/1.0/vts/functional/Android.bp
index 9a91560..29b31d2 100644
--- a/neuralnetworks/1.0/vts/functional/Android.bp
+++ b/neuralnetworks/1.0/vts/functional/Android.bp
@@ -25,19 +25,10 @@
 
 cc_defaults {
     name: "neuralnetworks_vts_functional_defaults",
-    defaults: ["VtsHalTargetTestDefaults"],
-    arch: {
-        x86: {
-            cflags: [ "-D_Float16=__fp16",
-                      "-Xclang", "-fnative-half-type",
-                      "-Xclang", "-fallow-half-arguments-and-returns" ],
-        },
-        x86_64: {
-            cflags: [ "-D_Float16=__fp16",
-                      "-Xclang", "-fnative-half-type",
-                      "-Xclang", "-fallow-half-arguments-and-returns" ],
-        },
-    },
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "neuralnetworks_float16",
+    ],
 }
 
 cc_library_static {
@@ -59,7 +50,7 @@
         "libgmock",
         "libhidlmemory",
         "libneuralnetworks_generated_test_harness",
-        "libneuralnetworks_utils",
+        "libneuralnetworks_common",
     ],
     header_libs: [
         "libneuralnetworks_headers",
@@ -83,14 +74,14 @@
         "libnativewindow",
     ],
     static_libs: [
+        "VtsHalNeuralNetworksV1_0_utils",
         "android.hardware.neuralnetworks@1.0",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
         "libgmock",
         "libhidlmemory",
         "libneuralnetworks_generated_test_harness",
-        "libneuralnetworks_utils",
-        "VtsHalNeuralNetworksV1_0_utils",
+        "libneuralnetworks_common",
     ],
     whole_static_libs: [
         "neuralnetworks_generated_V1_0_example",
@@ -98,5 +89,8 @@
     header_libs: [
         "libneuralnetworks_headers",
     ],
-    test_suites: ["general-tests", "vts"],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
 }
diff --git a/neuralnetworks/1.1/utils/Android.bp b/neuralnetworks/1.1/utils/Android.bp
index d9e82d4..4b8999f 100644
--- a/neuralnetworks/1.1/utils/Android.bp
+++ b/neuralnetworks/1.1/utils/Android.bp
@@ -31,43 +31,38 @@
     export_include_dirs: ["include"],
     cflags: ["-Wthread-safety"],
     static_libs: [
+        "android.hardware.neuralnetworks@1.0",
+        "android.hardware.neuralnetworks@1.1",
         "neuralnetworks_types",
         "neuralnetworks_utils_hal_common",
         "neuralnetworks_utils_hal_1_0",
     ],
-    shared_libs: [
-        "android.hardware.neuralnetworks@1.0",
-        "android.hardware.neuralnetworks@1.1",
-    ],
-    export_static_lib_headers: [
-        "neuralnetworks_utils_hal_common",
-    ],
 }
 
 cc_test {
     name: "neuralnetworks_utils_hal_1_1_test",
+    host_supported: true,
     srcs: ["test/*.cpp"],
     static_libs: [
         "android.hardware.neuralnetworks@1.0",
         "android.hardware.neuralnetworks@1.1",
         "libgmock",
-        "libneuralnetworks_common",
         "neuralnetworks_types",
         "neuralnetworks_utils_hal_common",
         "neuralnetworks_utils_hal_1_0",
         "neuralnetworks_utils_hal_1_1",
     ],
     shared_libs: [
-        "android.hidl.allocator@1.0",
-        "android.hidl.memory@1.0",
         "libbase",
         "libcutils",
-        "libfmq",
         "libhidlbase",
-        "libhidlmemory",
         "liblog",
-        "libnativewindow",
         "libutils",
     ],
+    target: {
+        android: {
+            shared_libs: ["libnativewindow"],
+        },
+    },
     test_suites: ["general-tests"],
 }
diff --git a/neuralnetworks/1.1/utils/OWNERS b/neuralnetworks/1.1/utils/OWNERS
deleted file mode 100644
index e4feee3..0000000
--- a/neuralnetworks/1.1/utils/OWNERS
+++ /dev/null
@@ -1,11 +0,0 @@
-# Neuralnetworks team
-butlermichael@google.com
-dgross@google.com
-galarragas@google.com
-jeanluc@google.com
-levp@google.com
-miaowang@google.com
-pszczepaniak@google.com
-slavash@google.com
-vddang@google.com
-xusongw@google.com
diff --git a/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Device.h b/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Device.h
index 5e224b5..38ca138 100644
--- a/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Device.h
+++ b/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Device.h
@@ -23,8 +23,8 @@
 #include <nnapi/OperandTypes.h>
 #include <nnapi/Result.h>
 #include <nnapi/Types.h>
+#include <nnapi/hal/1.0/ProtectCallback.h>
 #include <nnapi/hal/CommonUtils.h>
-#include <nnapi/hal/ProtectCallback.h>
 
 #include <functional>
 #include <memory>
@@ -64,8 +64,9 @@
     nn::GeneralResult<nn::SharedPreparedModel> prepareModel(
             const nn::Model& model, nn::ExecutionPreference preference, nn::Priority priority,
             nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
-            const std::vector<nn::SharedHandle>& dataCache,
-            const nn::CacheToken& token) const override;
+            const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
 
     nn::GeneralResult<nn::SharedPreparedModel> prepareModelFromCache(
             nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
diff --git a/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Utils.h b/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Utils.h
index a8cf8cf..ff06739 100644
--- a/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Utils.h
+++ b/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Utils.h
@@ -26,12 +26,11 @@
 #include <nnapi/Types.h>
 #include <nnapi/Validation.h>
 #include <nnapi/hal/1.0/Conversions.h>
-#include <nnapi/hal/HandleError.h>
 
 namespace android::hardware::neuralnetworks::V1_1::utils {
 
 constexpr auto kDefaultExecutionPreference = ExecutionPreference::FAST_SINGLE_ANSWER;
-constexpr auto kVersion = nn::Version::ANDROID_P;
+constexpr auto kVersion = nn::kVersionFeatureLevel2;
 
 template <typename Type>
 nn::Result<void> validate(const Type& halObject) {
@@ -52,9 +51,9 @@
 }
 
 template <typename Type>
-nn::GeneralResult<void> compliantVersion(const Type& canonical) {
-    const auto version = NN_TRY(hal::utils::makeGeneralFailure(nn::validate(canonical)));
-    if (version > kVersion) {
+nn::Result<void> compliantVersion(const Type& canonical) {
+    const auto version = NN_TRY(nn::validate(canonical));
+    if (!nn::isCompliantVersion(version, kVersion)) {
         return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion;
     }
     return {};
diff --git a/neuralnetworks/1.1/utils/src/Conversions.cpp b/neuralnetworks/1.1/utils/src/Conversions.cpp
index 467ceb3..887c8ec 100644
--- a/neuralnetworks/1.1/utils/src/Conversions.cpp
+++ b/neuralnetworks/1.1/utils/src/Conversions.cpp
@@ -88,8 +88,9 @@
 }
 
 GeneralResult<Operation> unvalidatedConvert(const hal::V1_1::Operation& operation) {
+    const auto type = NN_TRY(unvalidatedConvert(operation.type));
     return Operation{
-            .type = NN_TRY(unvalidatedConvert(operation.type)),
+            .type = type,
             .inputs = operation.inputs,
             .outputs = operation.outputs,
     };
@@ -100,7 +101,7 @@
 
     // Verify number of consumers.
     const auto numberOfConsumers =
-            NN_TRY(hal::utils::countNumberOfConsumers(model.operands.size(), operations));
+            NN_TRY(countNumberOfConsumers(model.operands.size(), operations));
     CHECK(model.operands.size() == numberOfConsumers.size());
     for (size_t i = 0; i < model.operands.size(); ++i) {
         if (model.operands[i].numberOfConsumers != numberOfConsumers[i]) {
@@ -110,17 +111,20 @@
         }
     }
 
+    auto operands = NN_TRY(unvalidatedConvert(model.operands));
     auto main = Model::Subgraph{
-            .operands = NN_TRY(unvalidatedConvert(model.operands)),
+            .operands = std::move(operands),
             .operations = std::move(operations),
             .inputIndexes = model.inputIndexes,
             .outputIndexes = model.outputIndexes,
     };
 
+    auto operandValues = NN_TRY(unvalidatedConvert(model.operandValues));
+    auto pools = NN_TRY(unvalidatedConvert(model.pools));
     return Model{
             .main = std::move(main),
-            .operandValues = NN_TRY(unvalidatedConvert(model.operandValues)),
-            .pools = NN_TRY(unvalidatedConvert(model.pools)),
+            .operandValues = std::move(operandValues),
+            .pools = std::move(pools),
             .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
     };
 }
@@ -195,19 +199,23 @@
 }
 
 nn::GeneralResult<Capabilities> unvalidatedConvert(const nn::Capabilities& capabilities) {
+    const auto float32Performance = NN_TRY(unvalidatedConvert(
+            capabilities.operandPerformance.lookup(nn::OperandType::TENSOR_FLOAT32)));
+    const auto quanitized8Performance = NN_TRY(unvalidatedConvert(
+            capabilities.operandPerformance.lookup(nn::OperandType::TENSOR_QUANT8_ASYMM)));
+    const auto relaxedFloat32toFloat16Performance =
+            NN_TRY(unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor));
     return Capabilities{
-            .float32Performance = NN_TRY(unvalidatedConvert(
-                    capabilities.operandPerformance.lookup(nn::OperandType::TENSOR_FLOAT32))),
-            .quantized8Performance = NN_TRY(unvalidatedConvert(
-                    capabilities.operandPerformance.lookup(nn::OperandType::TENSOR_QUANT8_ASYMM))),
-            .relaxedFloat32toFloat16Performance = NN_TRY(
-                    unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor)),
+            .float32Performance = float32Performance,
+            .quantized8Performance = quanitized8Performance,
+            .relaxedFloat32toFloat16Performance = relaxedFloat32toFloat16Performance,
     };
 }
 
 nn::GeneralResult<Operation> unvalidatedConvert(const nn::Operation& operation) {
+    const auto type = NN_TRY(unvalidatedConvert(operation.type));
     return Operation{
-            .type = NN_TRY(unvalidatedConvert(operation.type)),
+            .type = type,
             .inputs = operation.inputs,
             .outputs = operation.outputs,
     };
@@ -223,19 +231,22 @@
 
     // Update number of consumers.
     const auto numberOfConsumers =
-            NN_TRY(hal::utils::countNumberOfConsumers(operands.size(), model.main.operations));
+            NN_TRY(countNumberOfConsumers(operands.size(), model.main.operations));
     CHECK(operands.size() == numberOfConsumers.size());
     for (size_t i = 0; i < operands.size(); ++i) {
         operands[i].numberOfConsumers = numberOfConsumers[i];
     }
 
+    auto operations = NN_TRY(unvalidatedConvert(model.main.operations));
+    auto operandValues = NN_TRY(unvalidatedConvert(model.operandValues));
+    auto pools = NN_TRY(unvalidatedConvert(model.pools));
     return Model{
             .operands = std::move(operands),
-            .operations = NN_TRY(unvalidatedConvert(model.main.operations)),
+            .operations = std::move(operations),
             .inputIndexes = model.main.inputIndexes,
             .outputIndexes = model.main.outputIndexes,
-            .operandValues = NN_TRY(unvalidatedConvert(model.operandValues)),
-            .pools = NN_TRY(unvalidatedConvert(model.pools)),
+            .operandValues = std::move(operandValues),
+            .pools = std::move(pools),
             .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
     };
 }
diff --git a/neuralnetworks/1.1/utils/src/Device.cpp b/neuralnetworks/1.1/utils/src/Device.cpp
index 3197ef4..28f3276 100644
--- a/neuralnetworks/1.1/utils/src/Device.cpp
+++ b/neuralnetworks/1.1/utils/src/Device.cpp
@@ -29,9 +29,9 @@
 #include <nnapi/Result.h>
 #include <nnapi/Types.h>
 #include <nnapi/hal/1.0/Callbacks.h>
+#include <nnapi/hal/1.0/HandleError.h>
+#include <nnapi/hal/1.0/ProtectCallback.h>
 #include <nnapi/hal/CommonUtils.h>
-#include <nnapi/hal/HandleError.h>
-#include <nnapi/hal/ProtectCallback.h>
 
 #include <functional>
 #include <memory>
@@ -47,7 +47,7 @@
 
 nn::GeneralResult<nn::Capabilities> capabilitiesCallback(V1_0::ErrorStatus status,
                                                          const Capabilities& capabilities) {
-    HANDLE_HAL_STATUS(status) << "getting capabilities failed with " << toString(status);
+    HANDLE_STATUS_HIDL(status) << "getting capabilities failed with " << toString(status);
     return nn::convert(capabilities);
 }
 
@@ -99,7 +99,7 @@
 }
 
 nn::Version Device::getFeatureLevel() const {
-    return nn::Version::ANDROID_P;
+    return kVersion;
 }
 
 nn::DeviceType Device::getType() const {
@@ -143,7 +143,9 @@
 nn::GeneralResult<nn::SharedPreparedModel> Device::prepareModel(
         const nn::Model& model, nn::ExecutionPreference preference, nn::Priority /*priority*/,
         nn::OptionalTimePoint /*deadline*/, const std::vector<nn::SharedHandle>& /*modelCache*/,
-        const std::vector<nn::SharedHandle>& /*dataCache*/, const nn::CacheToken& /*token*/) const {
+        const std::vector<nn::SharedHandle>& /*dataCache*/, const nn::CacheToken& /*token*/,
+        const std::vector<nn::TokenValuePair>& /*hints*/,
+        const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
     // Ensure that model is ready for IPC.
     std::optional<nn::Model> maybeModelInShared;
     const nn::Model& modelInShared =
@@ -157,7 +159,7 @@
 
     const auto ret = kDevice->prepareModel_1_1(hidlModel, hidlPreference, cb);
     const auto status = HANDLE_TRANSPORT_FAILURE(ret);
-    HANDLE_HAL_STATUS(status) << "model preparation failed with " << toString(status);
+    HANDLE_STATUS_HIDL(status) << "model preparation failed with " << toString(status);
 
     return cb->get();
 }
diff --git a/neuralnetworks/1.1/utils/test/DeviceTest.cpp b/neuralnetworks/1.1/utils/test/DeviceTest.cpp
index 41e0e30..8ab87bc 100644
--- a/neuralnetworks/1.1/utils/test/DeviceTest.cpp
+++ b/neuralnetworks/1.1/utils/test/DeviceTest.cpp
@@ -243,7 +243,7 @@
     const auto featureLevel = device->getFeatureLevel();
 
     // verify result
-    EXPECT_EQ(featureLevel, nn::Version::ANDROID_P);
+    EXPECT_EQ(featureLevel, nn::kVersionFeatureLevel2);
 }
 
 TEST(DeviceTest, getCachedData) {
@@ -390,7 +390,7 @@
 
     // run test
     const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
-                                             nn::Priority::DEFAULT, {}, {}, {}, {});
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_TRUE(result.has_value())
@@ -409,7 +409,7 @@
 
     // run test
     const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
-                                             nn::Priority::DEFAULT, {}, {}, {}, {});
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -427,7 +427,7 @@
 
     // run test
     const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
-                                             nn::Priority::DEFAULT, {}, {}, {}, {});
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -445,7 +445,7 @@
 
     // run test
     const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
-                                             nn::Priority::DEFAULT, {}, {}, {}, {});
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -462,7 +462,7 @@
 
     // run test
     const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
-                                             nn::Priority::DEFAULT, {}, {}, {}, {});
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -479,7 +479,7 @@
 
     // run test
     const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
-                                             nn::Priority::DEFAULT, {}, {}, {}, {});
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -498,7 +498,7 @@
 
     // run test
     const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
-                                             nn::Priority::DEFAULT, {}, {}, {}, {});
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
diff --git a/neuralnetworks/1.1/vts/OWNERS b/neuralnetworks/1.1/vts/OWNERS
deleted file mode 100644
index b5a8e1f..0000000
--- a/neuralnetworks/1.1/vts/OWNERS
+++ /dev/null
@@ -1,16 +0,0 @@
-# Neuralnetworks team
-butlermichael@google.com
-dgross@google.com
-jeanluc@google.com
-levp@google.com
-miaowang@google.com
-mikie@google.com
-mks@google.com
-pszczepaniak@google.com
-slavash@google.com
-vddang@google.com
-xusongw@google.com
-
-# VTS team
-yim@google.com
-yuexima@google.com
diff --git a/neuralnetworks/1.1/vts/functional/Android.bp b/neuralnetworks/1.1/vts/functional/Android.bp
index 826ba96..e9d4b76 100644
--- a/neuralnetworks/1.1/vts/functional/Android.bp
+++ b/neuralnetworks/1.1/vts/functional/Android.bp
@@ -28,18 +28,19 @@
     defaults: ["neuralnetworks_vts_functional_defaults"],
     srcs: [
         "BasicTests.cpp",
+        "GeneratedTestHarness.cpp",
         "TestAssertions.cpp",
         "TestMain.cpp",
         "ValidateModel.cpp",
         "ValidateRequest.cpp",
         "VtsHalNeuralnetworks.cpp",
-        "GeneratedTestHarness.cpp",
     ],
     shared_libs: [
         "libfmq",
         "libnativewindow",
     ],
     static_libs: [
+        "VtsHalNeuralNetworksV1_0_utils",
         "android.hardware.neuralnetworks@1.0",
         "android.hardware.neuralnetworks@1.1",
         "android.hidl.allocator@1.0",
@@ -47,8 +48,7 @@
         "libgmock",
         "libhidlmemory",
         "libneuralnetworks_generated_test_harness",
-        "libneuralnetworks_utils",
-        "VtsHalNeuralNetworksV1_0_utils",
+        "libneuralnetworks_common",
     ],
     whole_static_libs: [
         "neuralnetworks_generated_V1_0_example",
@@ -57,5 +57,8 @@
     header_libs: [
         "libneuralnetworks_headers",
     ],
-    test_suites: ["general-tests", "vts"],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
 }
diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal
index f5b6ead..ccb0f30 100644
--- a/neuralnetworks/1.2/types.hal
+++ b/neuralnetworks/1.2/types.hal
@@ -80,7 +80,7 @@
      * - scales: an array of positive 32 bit floating point values.
      * The size of the scales array must be equal to dimensions[channelDim].
      *
-     *{@link SymmPerChannelQuantParams} must hold the parameters for an Operand of this type.
+     * {@link SymmPerChannelQuantParams} must hold the parameters for an Operand of this type.
      * The channel dimension of this tensor must not be unknown (dimensions[channelDim] != 0).
      *
      * The formula is:
diff --git a/neuralnetworks/1.2/utils/Android.bp b/neuralnetworks/1.2/utils/Android.bp
index 41281ee..e7d514f 100644
--- a/neuralnetworks/1.2/utils/Android.bp
+++ b/neuralnetworks/1.2/utils/Android.bp
@@ -31,19 +31,14 @@
     export_include_dirs: ["include"],
     cflags: ["-Wthread-safety"],
     static_libs: [
-        "neuralnetworks_types",
-        "neuralnetworks_utils_hal_common",
-        "neuralnetworks_utils_hal_1_0",
-        "neuralnetworks_utils_hal_1_1",
-    ],
-    shared_libs: [
         "android.hardware.neuralnetworks@1.0",
         "android.hardware.neuralnetworks@1.1",
         "android.hardware.neuralnetworks@1.2",
         "libfmq",
-    ],
-    export_static_lib_headers: [
+        "neuralnetworks_types",
         "neuralnetworks_utils_hal_common",
+        "neuralnetworks_utils_hal_1_0",
+        "neuralnetworks_utils_hal_1_1",
     ],
     product_variables: {
         debuggable: { // eng and userdebug builds
@@ -54,13 +49,17 @@
 
 cc_test {
     name: "neuralnetworks_utils_hal_1_2_test",
+    host_supported: true,
+    tidy_timeout_srcs: [
+        "test/DeviceTest.cpp",
+        "test/PreparedModelTest.cpp",
+    ],
     srcs: ["test/*.cpp"],
     static_libs: [
         "android.hardware.neuralnetworks@1.0",
         "android.hardware.neuralnetworks@1.1",
         "android.hardware.neuralnetworks@1.2",
         "libgmock",
-        "libneuralnetworks_common",
         "neuralnetworks_types",
         "neuralnetworks_utils_hal_common",
         "neuralnetworks_utils_hal_1_0",
@@ -68,16 +67,17 @@
         "neuralnetworks_utils_hal_1_2",
     ],
     shared_libs: [
-        "android.hidl.allocator@1.0",
-        "android.hidl.memory@1.0",
         "libbase",
         "libcutils",
         "libfmq",
         "libhidlbase",
-        "libhidlmemory",
         "liblog",
-        "libnativewindow",
         "libutils",
     ],
+    target: {
+        android: {
+            shared_libs: ["libnativewindow"],
+        },
+    },
     test_suites: ["general-tests"],
 }
diff --git a/neuralnetworks/1.2/utils/OWNERS b/neuralnetworks/1.2/utils/OWNERS
deleted file mode 100644
index e4feee3..0000000
--- a/neuralnetworks/1.2/utils/OWNERS
+++ /dev/null
@@ -1,11 +0,0 @@
-# Neuralnetworks team
-butlermichael@google.com
-dgross@google.com
-galarragas@google.com
-jeanluc@google.com
-levp@google.com
-miaowang@google.com
-pszczepaniak@google.com
-slavash@google.com
-vddang@google.com
-xusongw@google.com
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Burst.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Burst.h
new file mode 100644
index 0000000..1b28476
--- /dev/null
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Burst.h
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_UTILS_BURST_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_UTILS_BURST_H
+
+#include "nnapi/hal/1.2/BurstUtils.h"
+
+#include <android-base/thread_annotations.h>
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware/neuralnetworks/1.2/IBurstCallback.h>
+#include <android/hardware/neuralnetworks/1.2/IBurstContext.h>
+#include <android/hardware/neuralnetworks/1.2/IPreparedModel.h>
+#include <android/hardware/neuralnetworks/1.2/types.h>
+#include <fmq/MessageQueue.h>
+#include <hidl/MQDescriptor.h>
+#include <nnapi/IBurst.h>
+#include <nnapi/IExecution.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/1.0/ProtectCallback.h>
+#include <nnapi/hal/CommonUtils.h>
+
+#include <atomic>
+#include <chrono>
+#include <functional>
+#include <map>
+#include <memory>
+#include <mutex>
+#include <stack>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::V1_2::utils {
+
+/**
+ * The Burst class manages both the serialization and deserialization of data across FMQ, making it
+ * appear to the runtime as a regular synchronous inference. Additionally, this class manages the
+ * burst's memory cache.
+ */
+class Burst final : public nn::IBurst, public std::enable_shared_from_this<Burst> {
+    struct PrivateConstructorTag {};
+
+  public:
+    using FallbackFunction = std::function<
+            nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>()>;
+
+    /**
+     * NN runtime memory cache.
+     *
+     * MemoryCache associates a Memory object with a slot number to be passed across FMQ. The
+     * ExecutionBurstServer can use this callback to retrieve a hidl_memory corresponding to the
+     * slot via HIDL.
+     *
+     * Whenever a hidl_memory object is copied, it will duplicate the underlying file descriptor.
+     * Because the NN runtime currently copies the hidl_memory on each execution, it is difficult to
+     * associate hidl_memory objects with previously cached hidl_memory objects. For this reason,
+     * callers of this class must pair each hidl_memory object with an associated key. For
+     * efficiency, if two hidl_memory objects represent the same underlying buffer, they must use
+     * the same key.
+     *
+     * This class is thread-safe.
+     */
+    class MemoryCache : public std::enable_shared_from_this<MemoryCache> {
+        struct PrivateConstructorTag {};
+
+      public:
+        using Task = std::function<void()>;
+        using Cleanup = base::ScopeGuard<Task>;
+        using SharedCleanup = std::shared_ptr<const Cleanup>;
+        using WeakCleanup = std::weak_ptr<const Cleanup>;
+
+        // Custom constructor to pre-allocate cache sizes.
+        MemoryCache();
+
+        /**
+         * Add a burst context to the MemoryCache object.
+         *
+         * If this method is called, it must be called before the MemoryCache::cacheMemory or
+         * MemoryCache::getMemory is used.
+         *
+         * @param burstContext Burst context to be added to the MemoryCache object.
+         */
+        void setBurstContext(sp<IBurstContext> burstContext);
+
+        /**
+         * Cache a memory object in the MemoryCache object.
+         *
+         * @param memory Memory object to be cached while the returned `SharedCleanup` is alive.
+         * @return A pair of (1) a unique identifier for the cache entry and (2) a ref-counted
+         *     "hold" object which preserves the cache as long as the hold object is alive.
+         */
+        std::pair<int32_t, SharedCleanup> cacheMemory(const nn::SharedMemory& memory);
+
+        /**
+         * Get the memory object corresponding to a slot identifier.
+         *
+         * @param slot Slot which identifies the memory object to retrieve.
+         * @return The memory object corresponding to slot, otherwise GeneralError.
+         */
+        nn::GeneralResult<nn::SharedMemory> getMemory(int32_t slot);
+
+      private:
+        void freeMemory(const nn::SharedMemory& memory);
+        int32_t allocateSlotLocked() REQUIRES(mMutex);
+
+        std::mutex mMutex;
+        std::condition_variable mCond;
+        sp<IBurstContext> mBurstContext GUARDED_BY(mMutex);
+        std::stack<int32_t, std::vector<int32_t>> mFreeSlots GUARDED_BY(mMutex);
+        std::map<nn::SharedMemory, int32_t> mMemoryIdToSlot GUARDED_BY(mMutex);
+        std::vector<nn::SharedMemory> mMemoryCache GUARDED_BY(mMutex);
+        std::vector<WeakCleanup> mCacheCleaner GUARDED_BY(mMutex);
+    };
+
+    /**
+     * HIDL Callback class to pass memory objects to the Burst server when given corresponding
+     * slots.
+     */
+    class ExecutionBurstCallback : public IBurstCallback {
+      public:
+        // Precondition: memoryCache must be non-null.
+        explicit ExecutionBurstCallback(const std::shared_ptr<MemoryCache>& memoryCache);
+
+        // See IBurstCallback::getMemories for information on this method.
+        Return<void> getMemories(const hidl_vec<int32_t>& slots, getMemories_cb cb) override;
+
+      private:
+        const std::weak_ptr<MemoryCache> kMemoryCache;
+    };
+
+    /**
+     * Creates a burst controller on a prepared model.
+     *
+     * @param preparedModel Model prepared for execution to execute on.
+     * @param pollingTimeWindow How much time (in microseconds) the Burst is allowed to poll the FMQ
+     *     before waiting on the blocking futex. Polling may result in lower latencies at the
+     *     potential cost of more power usage.
+     * @return Burst Execution burst controller object.
+     */
+    static nn::GeneralResult<std::shared_ptr<const Burst>> create(
+            nn::SharedPreparedModel preparedModel, const sp<IPreparedModel>& hidlPreparedModel,
+            std::chrono::microseconds pollingTimeWindow);
+
+    Burst(PrivateConstructorTag tag, nn::SharedPreparedModel preparedModel,
+          std::unique_ptr<RequestChannelSender> requestChannelSender,
+          std::unique_ptr<ResultChannelReceiver> resultChannelReceiver,
+          sp<ExecutionBurstCallback> callback, sp<IBurstContext> burstContext,
+          std::shared_ptr<MemoryCache> memoryCache,
+          neuralnetworks::utils::DeathHandler deathHandler);
+
+    // See IBurst::cacheMemory for information on this method.
+    OptionalCacheHold cacheMemory(const nn::SharedMemory& memory) const override;
+
+    // See IBurst::execute for information on this method.
+    nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
+            const nn::Request& request, nn::MeasureTiming measure,
+            const nn::OptionalTimePoint& deadline, const nn::OptionalDuration& loopTimeoutDuration,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
+
+    // See IBurst::createReusableExecution for information on this method.
+    nn::GeneralResult<nn::SharedExecution> createReusableExecution(
+            const nn::Request& request, nn::MeasureTiming measure,
+            const nn::OptionalDuration& loopTimeoutDuration,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
+
+    // If fallback is not nullptr, this method will invoke the fallback function to try another
+    // execution path if the packet could not be sent. Otherwise, failing to send the packet will
+    // result in an error.
+    nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> executeInternal(
+            const std::vector<FmqRequestDatum>& requestPacket,
+            const hal::utils::RequestRelocation& relocation, FallbackFunction fallback) const;
+
+  private:
+    mutable std::atomic_flag mExecutionInFlight = ATOMIC_FLAG_INIT;
+    const nn::SharedPreparedModel kPreparedModel;
+    const std::unique_ptr<RequestChannelSender> mRequestChannelSender;
+    const std::unique_ptr<ResultChannelReceiver> mResultChannelReceiver;
+    const sp<ExecutionBurstCallback> mBurstCallback;
+    const sp<IBurstContext> mBurstContext;
+    const std::shared_ptr<MemoryCache> mMemoryCache;
+    // `kDeathHandler` must come after `mRequestChannelSender` and `mResultChannelReceiver` because
+    // it holds references to both objects.
+    const neuralnetworks::utils::DeathHandler kDeathHandler;
+};
+
+}  // namespace android::hardware::neuralnetworks::V1_2::utils
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_UTILS_BURST_H
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/BurstUtils.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/BurstUtils.h
new file mode 100644
index 0000000..7a6a241
--- /dev/null
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/BurstUtils.h
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_UTILS_BURST_UTILS_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_UTILS_BURST_UTILS_H
+
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware/neuralnetworks/1.2/types.h>
+#include <fmq/MessageQueue.h>
+#include <hidl/MQDescriptor.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/1.0/ProtectCallback.h>
+
+#include <atomic>
+#include <chrono>
+#include <memory>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::V1_2::utils {
+
+/**
+ * Number of elements in the FMQ.
+ */
+constexpr const size_t kExecutionBurstChannelLength = 1024;
+
+/**
+ * Get how long the burst controller should poll while waiting for results to be returned.
+ *
+ * This time can be affected by the property "debug.nn.burst-controller-polling-window".
+ *
+ * @return Polling time in microseconds.
+ */
+std::chrono::microseconds getBurstControllerPollingTimeWindow();
+
+/**
+ * Get how long the burst server should poll while waiting for a request to be received.
+ *
+ * This time can be affected by the property "debug.nn.burst-server-polling-window".
+ *
+ * @return Polling time in microseconds.
+ */
+std::chrono::microseconds getBurstServerPollingTimeWindow();
+
+/**
+ * Function to serialize a request.
+ *
+ * @param request Request object without the pool information.
+ * @param measure Whether to collect timing information for the execution.
+ * @param memoryIds Slot identifiers corresponding to memory resources for the request.
+ * @return Serialized FMQ request data.
+ */
+std::vector<FmqRequestDatum> serialize(const V1_0::Request& request, MeasureTiming measure,
+                                       const std::vector<int32_t>& slots);
+
+/**
+ * Deserialize the FMQ request data.
+ *
+ * The three resulting fields are the Request object (where Request::pools is empty), slot
+ * identifiers (which are stand-ins for Request::pools), and whether timing information must be
+ * collected for the run.
+ *
+ * @param data Serialized FMQ request data.
+ * @return Request object if successfully deserialized, otherwise an error message.
+ */
+nn::Result<std::tuple<V1_0::Request, std::vector<int32_t>, MeasureTiming>> deserialize(
+        const std::vector<FmqRequestDatum>& data);
+
+/**
+ * Function to serialize results.
+ *
+ * @param errorStatus Status of the execution.
+ * @param outputShapes Dynamic shapes of the output tensors.
+ * @param timing Timing information of the execution.
+ * @return Serialized FMQ result data.
+ */
+std::vector<FmqResultDatum> serialize(V1_0::ErrorStatus errorStatus,
+                                      const std::vector<OutputShape>& outputShapes, Timing timing);
+
+/**
+ * Deserialize the FMQ result data.
+ *
+ * The three resulting fields are the status of the execution, the dynamic shapes of the output
+ * tensors, and the timing information of the execution.
+ *
+ * @param data Serialized FMQ result data.
+ * @return Result object if successfully deserialized, otherwise an error message.
+ */
+nn::Result<std::tuple<V1_0::ErrorStatus, std::vector<OutputShape>, Timing>> deserialize(
+        const std::vector<FmqResultDatum>& data);
+
+/**
+ * RequestChannelSender is responsible for serializing the result packet of information, sending it
+ * on the result channel, and signaling that the data is available.
+ */
+class RequestChannelSender final : public neuralnetworks::utils::IProtectedCallback {
+    struct PrivateConstructorTag {};
+
+  public:
+    /**
+     * Create the sending end of a request channel.
+     *
+     * @param channelLength Number of elements in the FMQ.
+     * @return A pair of ResultChannelReceiver and the FMQ descriptor on successful creation,
+     *     GeneralError otherwise.
+     */
+    static nn::GeneralResult<std::pair<std::unique_ptr<RequestChannelSender>,
+                                       const MQDescriptorSync<FmqRequestDatum>*>>
+    create(size_t channelLength);
+
+    /**
+     * Send the request to the channel.
+     *
+     * @param request Request object without the pool information.
+     * @param measure Whether to collect timing information for the execution.
+     * @param slots Slot identifiers corresponding to memory resources for the request.
+     * @return An empty `Result` on successful send, otherwise an error message.
+     */
+    nn::Result<void> send(const V1_0::Request& request, MeasureTiming measure,
+                          const std::vector<int32_t>& slots);
+
+    /**
+     * Method to mark the channel as invalid, causing all future calls to RequestChannelSender::send
+     * to immediately return false without attempting to send a message across the FMQ.
+     */
+    void notifyAsDeadObject() override;
+
+    // prefer calling RequestChannelSender::send
+    nn::Result<void> sendPacket(const std::vector<FmqRequestDatum>& packet);
+
+    RequestChannelSender(PrivateConstructorTag tag, size_t channelLength);
+
+  private:
+    MessageQueue<FmqRequestDatum, kSynchronizedReadWrite> mFmqRequestChannel;
+    std::atomic<bool> mValid{true};
+};
+
+/**
+ * RequestChannelReceiver is responsible for waiting on the channel until the packet is available,
+ * extracting the packet from the channel, and deserializing the packet.
+ *
+ * Because the receiver can wait on a packet that may never come (e.g., because the sending side of
+ * the packet has been closed), this object can be invalidated, unblocking the receiver.
+ */
+class RequestChannelReceiver final {
+    struct PrivateConstructorTag {};
+
+  public:
+    /**
+     * Create the receiving end of a request channel.
+     *
+     * @param requestChannel Descriptor for the request channel.
+     * @param pollingTimeWindow How much time (in microseconds) the RequestChannelReceiver is
+     *     allowed to poll the FMQ before waiting on the blocking futex. Polling may result in lower
+     *     latencies at the potential cost of more power usage.
+     * @return RequestChannelReceiver on successful creation, nullptr otherwise.
+     */
+    static nn::GeneralResult<std::unique_ptr<RequestChannelReceiver>> create(
+            const MQDescriptorSync<FmqRequestDatum>& requestChannel,
+            std::chrono::microseconds pollingTimeWindow);
+
+    /**
+     * Get the request from the channel.
+     *
+     * This method will block until either:
+     * 1) The packet has been retrieved, or
+     * 2) The receiver has been invalidated
+     *
+     * @return Request object if successfully received, an appropriate message if error or if the
+     *     receiver object was invalidated.
+     */
+    nn::Result<std::tuple<V1_0::Request, std::vector<int32_t>, MeasureTiming>> getBlocking();
+
+    /**
+     * Method to mark the channel as invalid, unblocking any current or future calls to
+     * RequestChannelReceiver::getBlocking.
+     */
+    void invalidate();
+
+    RequestChannelReceiver(PrivateConstructorTag tag,
+                           const MQDescriptorSync<FmqRequestDatum>& requestChannel,
+                           std::chrono::microseconds pollingTimeWindow);
+
+  private:
+    nn::Result<std::vector<FmqRequestDatum>> getPacketBlocking();
+
+    MessageQueue<FmqRequestDatum, kSynchronizedReadWrite> mFmqRequestChannel;
+    std::atomic<bool> mTeardown{false};
+    const std::chrono::microseconds kPollingTimeWindow;
+};
+
+/**
+ * ResultChannelSender is responsible for serializing the result packet of information, sending it
+ * on the result channel, and signaling that the data is available.
+ */
+class ResultChannelSender final {
+    struct PrivateConstructorTag {};
+
+  public:
+    /**
+     * Create the sending end of a result channel.
+     *
+     * @param resultChannel Descriptor for the result channel.
+     * @return ResultChannelSender on successful creation, nullptr otherwise.
+     */
+    static nn::GeneralResult<std::unique_ptr<ResultChannelSender>> create(
+            const MQDescriptorSync<FmqResultDatum>& resultChannel);
+
+    /**
+     * Send the result to the channel.
+     *
+     * @param errorStatus Status of the execution.
+     * @param outputShapes Dynamic shapes of the output tensors.
+     * @param timing Timing information of the execution.
+     */
+    void send(V1_0::ErrorStatus errorStatus, const std::vector<OutputShape>& outputShapes,
+              Timing timing);
+
+    // prefer calling ResultChannelSender::send
+    void sendPacket(const std::vector<FmqResultDatum>& packet);
+
+    ResultChannelSender(PrivateConstructorTag tag,
+                        const MQDescriptorSync<FmqResultDatum>& resultChannel);
+
+  private:
+    MessageQueue<FmqResultDatum, kSynchronizedReadWrite> mFmqResultChannel;
+};
+
+/**
+ * ResultChannelReceiver is responsible for waiting on the channel until the packet is available,
+ * extracting the packet from the channel, and deserializing the packet.
+ *
+ * Because the receiver can wait on a packet that may never come (e.g., because the sending side of
+ * the packet has been closed), this object can be invalidated, unblocking the receiver.
+ */
+class ResultChannelReceiver final : public neuralnetworks::utils::IProtectedCallback {
+    struct PrivateConstructorTag {};
+
+  public:
+    /**
+     * Create the receiving end of a result channel.
+     *
+     * @param channelLength Number of elements in the FMQ.
+     * @param pollingTimeWindow How much time (in microseconds) the ResultChannelReceiver is allowed
+     *     to poll the FMQ before waiting on the blocking futex. Polling may result in lower
+     *     latencies at the potential cost of more power usage.
+     * @return A pair of ResultChannelReceiver and the FMQ descriptor on successful creation, or
+     *     GeneralError otherwise.
+     */
+    static nn::GeneralResult<std::pair<std::unique_ptr<ResultChannelReceiver>,
+                                       const MQDescriptorSync<FmqResultDatum>*>>
+    create(size_t channelLength, std::chrono::microseconds pollingTimeWindow);
+
+    /**
+     * Get the result from the channel.
+     *
+     * This method will block until either:
+     * 1) The packet has been retrieved, or
+     * 2) The receiver has been invalidated
+     *
+     * @return Result object if successfully received, otherwise an appropriate message if error or
+     *     if the receiver object was invalidated.
+     */
+    nn::Result<std::tuple<V1_0::ErrorStatus, std::vector<OutputShape>, Timing>> getBlocking();
+
+    /**
+     * Method to mark the channel as invalid, unblocking any current or future calls to
+     * ResultChannelReceiver::getBlocking.
+     */
+    void notifyAsDeadObject() override;
+
+    // prefer calling ResultChannelReceiver::getBlocking
+    nn::Result<std::vector<FmqResultDatum>> getPacketBlocking();
+
+    ResultChannelReceiver(PrivateConstructorTag tag, size_t channelLength,
+                          std::chrono::microseconds pollingTimeWindow);
+
+  private:
+    MessageQueue<FmqResultDatum, kSynchronizedReadWrite> mFmqResultChannel;
+    std::atomic<bool> mValid{true};
+    const std::chrono::microseconds kPollingTimeWindow;
+};
+
+}  // namespace android::hardware::neuralnetworks::V1_2::utils
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_UTILS_BURST_UTILS_H
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Callbacks.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Callbacks.h
index ba3c1ba..fc04303 100644
--- a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Callbacks.h
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Callbacks.h
@@ -27,8 +27,8 @@
 #include <nnapi/Result.h>
 #include <nnapi/Types.h>
 #include <nnapi/hal/1.0/Callbacks.h>
+#include <nnapi/hal/1.0/ProtectCallback.h>
 #include <nnapi/hal/CommonUtils.h>
-#include <nnapi/hal/ProtectCallback.h>
 #include <nnapi/hal/TransferValue.h>
 
 // See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
@@ -38,7 +38,8 @@
 
 // Converts the results of IDevice::prepareModel* to the NN canonical format. On success, this
 // function returns with a non-null nn::SharedPreparedModel with a feature level of
-// nn::Version::ANDROID_Q. On failure, this function returns with the appropriate nn::GeneralError.
+// nn::kVersionFeatureLevel3. On failure, this function returns with the appropriate
+// nn::GeneralError.
 nn::GeneralResult<nn::SharedPreparedModel> prepareModelCallback(
         V1_0::ErrorStatus status, const sp<IPreparedModel>& preparedModel);
 
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Conversions.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Conversions.h
index 272cee7..4f13adc 100644
--- a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Conversions.h
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Conversions.h
@@ -37,7 +37,7 @@
 GeneralResult<Operand::ExtraParams> unvalidatedConvert(
         const hal::V1_2::Operand::ExtraParams& extraParams);
 GeneralResult<Model> unvalidatedConvert(const hal::V1_2::Model& model);
-GeneralResult<Model::ExtensionNameAndPrefix> unvalidatedConvert(
+GeneralResult<ExtensionNameAndPrefix> unvalidatedConvert(
         const hal::V1_2::Model::ExtensionNameAndPrefix& extensionNameAndPrefix);
 GeneralResult<OutputShape> unvalidatedConvert(const hal::V1_2::OutputShape& outputShape);
 GeneralResult<MeasureTiming> unvalidatedConvert(const hal::V1_2::MeasureTiming& measureTiming);
@@ -45,7 +45,6 @@
 GeneralResult<Extension> unvalidatedConvert(const hal::V1_2::Extension& extension);
 GeneralResult<Extension::OperandTypeInformation> unvalidatedConvert(
         const hal::V1_2::Extension::OperandTypeInformation& operandTypeInformation);
-GeneralResult<SharedHandle> unvalidatedConvert(const hardware::hidl_handle& handle);
 
 GeneralResult<DeviceType> convert(const hal::V1_2::DeviceType& deviceType);
 GeneralResult<Capabilities> convert(const hal::V1_2::Capabilities& capabilities);
@@ -79,14 +78,13 @@
         const nn::Operand::ExtraParams& extraParams);
 nn::GeneralResult<Model> unvalidatedConvert(const nn::Model& model);
 nn::GeneralResult<Model::ExtensionNameAndPrefix> unvalidatedConvert(
-        const nn::Model::ExtensionNameAndPrefix& extensionNameAndPrefix);
+        const nn::ExtensionNameAndPrefix& extensionNameAndPrefix);
 nn::GeneralResult<OutputShape> unvalidatedConvert(const nn::OutputShape& outputShape);
 nn::GeneralResult<MeasureTiming> unvalidatedConvert(const nn::MeasureTiming& measureTiming);
 nn::GeneralResult<Timing> unvalidatedConvert(const nn::Timing& timing);
 nn::GeneralResult<Extension> unvalidatedConvert(const nn::Extension& extension);
 nn::GeneralResult<Extension::OperandTypeInformation> unvalidatedConvert(
         const nn::Extension::OperandTypeInformation& operandTypeInformation);
-nn::GeneralResult<hidl_handle> unvalidatedConvert(const nn::SharedHandle& handle);
 
 nn::GeneralResult<DeviceType> convert(const nn::DeviceType& deviceType);
 nn::GeneralResult<Capabilities> convert(const nn::Capabilities& capabilities);
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Device.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Device.h
index b4bef5e..d92cf50 100644
--- a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Device.h
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Device.h
@@ -23,8 +23,8 @@
 #include <nnapi/OperandTypes.h>
 #include <nnapi/Result.h>
 #include <nnapi/Types.h>
+#include <nnapi/hal/1.0/ProtectCallback.h>
 #include <nnapi/hal/CommonUtils.h>
-#include <nnapi/hal/ProtectCallback.h>
 
 #include <functional>
 #include <memory>
@@ -83,8 +83,9 @@
     nn::GeneralResult<nn::SharedPreparedModel> prepareModel(
             const nn::Model& model, nn::ExecutionPreference preference, nn::Priority priority,
             nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
-            const std::vector<nn::SharedHandle>& dataCache,
-            const nn::CacheToken& token) const override;
+            const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
 
     nn::GeneralResult<nn::SharedPreparedModel> prepareModelFromCache(
             nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Execution.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Execution.h
index 9c66446..867f181 100644
--- a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Execution.h
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Execution.h
@@ -21,8 +21,8 @@
 #include <nnapi/IExecution.h>
 #include <nnapi/Result.h>
 #include <nnapi/Types.h>
+#include <nnapi/hal/1.0/ProtectCallback.h>
 #include <nnapi/hal/CommonUtils.h>
-#include <nnapi/hal/ProtectCallback.h>
 
 #include "PreparedModel.h"
 
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/ExecutionBurstController.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/ExecutionBurstController.h
deleted file mode 100644
index dae1ff3..0000000
--- a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/ExecutionBurstController.h
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_UTILS_EXECUTION_BURST_CONTROLLER_H
-#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_UTILS_EXECUTION_BURST_CONTROLLER_H
-
-#include "ExecutionBurstUtils.h"
-
-#include <android-base/thread_annotations.h>
-#include <android/hardware/neuralnetworks/1.0/types.h>
-#include <android/hardware/neuralnetworks/1.2/IBurstCallback.h>
-#include <android/hardware/neuralnetworks/1.2/IBurstContext.h>
-#include <android/hardware/neuralnetworks/1.2/IPreparedModel.h>
-#include <android/hardware/neuralnetworks/1.2/types.h>
-#include <fmq/MessageQueue.h>
-#include <hidl/MQDescriptor.h>
-#include <nnapi/IBurst.h>
-#include <nnapi/IExecution.h>
-#include <nnapi/IPreparedModel.h>
-#include <nnapi/Result.h>
-#include <nnapi/Types.h>
-#include <nnapi/hal/CommonUtils.h>
-#include <nnapi/hal/ProtectCallback.h>
-
-#include <atomic>
-#include <chrono>
-#include <functional>
-#include <map>
-#include <memory>
-#include <mutex>
-#include <stack>
-#include <tuple>
-#include <utility>
-#include <vector>
-
-namespace android::hardware::neuralnetworks::V1_2::utils {
-
-/**
- * The ExecutionBurstController class manages both the serialization and deserialization of data
- * across FMQ, making it appear to the runtime as a regular synchronous inference. Additionally,
- * this class manages the burst's memory cache.
- */
-class ExecutionBurstController final
-    : public nn::IBurst,
-      public std::enable_shared_from_this<ExecutionBurstController> {
-    struct PrivateConstructorTag {};
-
-  public:
-    using FallbackFunction = std::function<
-            nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>()>;
-
-    /**
-     * NN runtime memory cache.
-     *
-     * MemoryCache associates a Memory object with a slot number to be passed across FMQ. The
-     * ExecutionBurstServer can use this callback to retrieve a hidl_memory corresponding to the
-     * slot via HIDL.
-     *
-     * Whenever a hidl_memory object is copied, it will duplicate the underlying file descriptor.
-     * Because the NN runtime currently copies the hidl_memory on each execution, it is difficult to
-     * associate hidl_memory objects with previously cached hidl_memory objects. For this reason,
-     * callers of this class must pair each hidl_memory object with an associated key. For
-     * efficiency, if two hidl_memory objects represent the same underlying buffer, they must use
-     * the same key.
-     *
-     * This class is thread-safe.
-     */
-    class MemoryCache : public std::enable_shared_from_this<MemoryCache> {
-        struct PrivateConstructorTag {};
-
-      public:
-        using Task = std::function<void()>;
-        using Cleanup = base::ScopeGuard<Task>;
-        using SharedCleanup = std::shared_ptr<const Cleanup>;
-        using WeakCleanup = std::weak_ptr<const Cleanup>;
-
-        // Custom constructor to pre-allocate cache sizes.
-        MemoryCache();
-
-        /**
-         * Add a burst context to the MemoryCache object.
-         *
-         * If this method is called, it must be called before the MemoryCache::cacheMemory or
-         * MemoryCache::getMemory is used.
-         *
-         * @param burstContext Burst context to be added to the MemoryCache object.
-         */
-        void setBurstContext(sp<IBurstContext> burstContext);
-
-        /**
-         * Cache a memory object in the MemoryCache object.
-         *
-         * @param memory Memory object to be cached while the returned `SharedCleanup` is alive.
-         * @return A pair of (1) a unique identifier for the cache entry and (2) a ref-counted
-         *     "hold" object which preserves the cache as long as the hold object is alive.
-         */
-        std::pair<int32_t, SharedCleanup> cacheMemory(const nn::SharedMemory& memory);
-
-        /**
-         * Get the memory object corresponding to a slot identifier.
-         *
-         * @param slot Slot which identifies the memory object to retrieve.
-         * @return The memory object corresponding to slot, otherwise GeneralError.
-         */
-        nn::GeneralResult<nn::SharedMemory> getMemory(int32_t slot);
-
-      private:
-        void freeMemory(const nn::SharedMemory& memory);
-        int32_t allocateSlotLocked() REQUIRES(mMutex);
-
-        std::mutex mMutex;
-        std::condition_variable mCond;
-        sp<IBurstContext> mBurstContext GUARDED_BY(mMutex);
-        std::stack<int32_t, std::vector<int32_t>> mFreeSlots GUARDED_BY(mMutex);
-        std::map<nn::SharedMemory, int32_t> mMemoryIdToSlot GUARDED_BY(mMutex);
-        std::vector<nn::SharedMemory> mMemoryCache GUARDED_BY(mMutex);
-        std::vector<WeakCleanup> mCacheCleaner GUARDED_BY(mMutex);
-    };
-
-    /**
-     * HIDL Callback class to pass memory objects to the Burst server when given corresponding
-     * slots.
-     */
-    class ExecutionBurstCallback : public IBurstCallback {
-      public:
-        // Precondition: memoryCache must be non-null.
-        explicit ExecutionBurstCallback(const std::shared_ptr<MemoryCache>& memoryCache);
-
-        // See IBurstCallback::getMemories for information on this method.
-        Return<void> getMemories(const hidl_vec<int32_t>& slots, getMemories_cb cb) override;
-
-      private:
-        const std::weak_ptr<MemoryCache> kMemoryCache;
-    };
-
-    /**
-     * Creates a burst controller on a prepared model.
-     *
-     * @param preparedModel Model prepared for execution to execute on.
-     * @param pollingTimeWindow How much time (in microseconds) the ExecutionBurstController is
-     *     allowed to poll the FMQ before waiting on the blocking futex. Polling may result in lower
-     *     latencies at the potential cost of more power usage.
-     * @return ExecutionBurstController Execution burst controller object.
-     */
-    static nn::GeneralResult<std::shared_ptr<const ExecutionBurstController>> create(
-            nn::SharedPreparedModel preparedModel, const sp<IPreparedModel>& hidlPreparedModel,
-            std::chrono::microseconds pollingTimeWindow);
-
-    ExecutionBurstController(PrivateConstructorTag tag, nn::SharedPreparedModel preparedModel,
-                             std::unique_ptr<RequestChannelSender> requestChannelSender,
-                             std::unique_ptr<ResultChannelReceiver> resultChannelReceiver,
-                             sp<ExecutionBurstCallback> callback, sp<IBurstContext> burstContext,
-                             std::shared_ptr<MemoryCache> memoryCache,
-                             neuralnetworks::utils::DeathHandler deathHandler);
-
-    // See IBurst::cacheMemory for information on this method.
-    OptionalCacheHold cacheMemory(const nn::SharedMemory& memory) const override;
-
-    // See IBurst::execute for information on this method.
-    nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
-            const nn::Request& request, nn::MeasureTiming measure,
-            const nn::OptionalTimePoint& deadline,
-            const nn::OptionalDuration& loopTimeoutDuration) const override;
-
-    // See IBurst::createReusableExecution for information on this method.
-    nn::GeneralResult<nn::SharedExecution> createReusableExecution(
-            const nn::Request& request, nn::MeasureTiming measure,
-            const nn::OptionalDuration& loopTimeoutDuration) const override;
-
-    // If fallback is not nullptr, this method will invoke the fallback function to try another
-    // execution path if the packet could not be sent. Otherwise, failing to send the packet will
-    // result in an error.
-    nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> executeInternal(
-            const std::vector<FmqRequestDatum>& requestPacket,
-            const hal::utils::RequestRelocation& relocation, FallbackFunction fallback) const;
-
-  private:
-    mutable std::atomic_flag mExecutionInFlight = ATOMIC_FLAG_INIT;
-    const nn::SharedPreparedModel kPreparedModel;
-    const std::unique_ptr<RequestChannelSender> mRequestChannelSender;
-    const std::unique_ptr<ResultChannelReceiver> mResultChannelReceiver;
-    const sp<ExecutionBurstCallback> mBurstCallback;
-    const sp<IBurstContext> mBurstContext;
-    const std::shared_ptr<MemoryCache> mMemoryCache;
-    // `kDeathHandler` must come after `mRequestChannelSender` and `mResultChannelReceiver` because
-    // it holds references to both objects.
-    const neuralnetworks::utils::DeathHandler kDeathHandler;
-};
-
-}  // namespace android::hardware::neuralnetworks::V1_2::utils
-
-#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_UTILS_EXECUTION_BURST_CONTROLLER_H
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/ExecutionBurstServer.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/ExecutionBurstServer.h
deleted file mode 100644
index f7926f5..0000000
--- a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/ExecutionBurstServer.h
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_UTILS_EXECUTION_BURST_SERVER_H
-#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_UTILS_EXECUTION_BURST_SERVER_H
-
-#include "ExecutionBurstUtils.h"
-
-#include <android-base/thread_annotations.h>
-#include <android/hardware/neuralnetworks/1.0/types.h>
-#include <android/hardware/neuralnetworks/1.2/IBurstCallback.h>
-#include <android/hardware/neuralnetworks/1.2/IPreparedModel.h>
-#include <android/hardware/neuralnetworks/1.2/types.h>
-#include <fmq/MessageQueue.h>
-#include <hidl/MQDescriptor.h>
-#include <nnapi/IBurst.h>
-#include <nnapi/Result.h>
-#include <nnapi/Types.h>
-#include <nnapi/hal/ProtectCallback.h>
-
-#include <atomic>
-#include <chrono>
-#include <memory>
-#include <optional>
-#include <thread>
-#include <tuple>
-#include <vector>
-
-namespace android::hardware::neuralnetworks::V1_2::utils {
-
-/**
- * The ExecutionBurstServer class is responsible for waiting for and deserializing a request object
- * from a FMQ, performing the inference, and serializing the result back across another FMQ.
- */
-class ExecutionBurstServer : public IBurstContext {
-    struct PrivateConstructorTag {};
-
-  public:
-    /**
-     * Class to cache the memory objects for a burst object.
-     *
-     * This class is thread-safe.
-     */
-    class MemoryCache {
-      public:
-        // Precondition: burstExecutor != nullptr
-        // Precondition: burstCallback != nullptr
-        MemoryCache(nn::SharedBurst burstExecutor, sp<IBurstCallback> burstCallback);
-
-        /**
-         * Get the cached memory objects corresponding to provided slot identifiers.
-         *
-         * If the slot entry is not present in the cache, this class will use IBurstCallback to
-         * retrieve those entries that are not present in the cache, then cache them.
-         *
-         * @param slots Identifiers of memory objects to be retrieved.
-         * @return A vector where each element is the memory object and a ref-counted cache "hold"
-         *     object to preserve the cache entry of the IBurst object as long as the "hold" object
-         *     is alive, otherwise GeneralError. Each element of the vector corresponds to the
-         *     element of slot.
-         */
-        nn::GeneralResult<std::vector<std::pair<nn::SharedMemory, nn::IBurst::OptionalCacheHold>>>
-        getCacheEntries(const std::vector<int32_t>& slots);
-
-        /**
-         * Remove an entry from the cache.
-         *
-         * @param slot Identifier of the memory object to be removed from the cache.
-         */
-        void removeCacheEntry(int32_t slot);
-
-      private:
-        nn::GeneralResult<void> ensureCacheEntriesArePresentLocked(
-                const std::vector<int32_t>& slots) REQUIRES(mMutex);
-        nn::GeneralResult<std::pair<nn::SharedMemory, nn::IBurst::OptionalCacheHold>>
-        getCacheEntryLocked(int32_t slot) REQUIRES(mMutex);
-        void addCacheEntryLocked(int32_t slot, nn::SharedMemory memory) REQUIRES(mMutex);
-
-        std::mutex mMutex;
-        std::map<int32_t, std::pair<nn::SharedMemory, nn::IBurst::OptionalCacheHold>> mCache
-                GUARDED_BY(mMutex);
-        nn::SharedBurst kBurstExecutor;
-        const sp<IBurstCallback> kBurstCallback;
-    };
-
-    /**
-     * Create automated context to manage FMQ-based executions.
-     *
-     * This function is intended to be used by a service to automatically:
-     * 1) Receive data from a provided FMQ
-     * 2) Execute a model with the given information
-     * 3) Send the result to the created FMQ
-     *
-     * @param callback Callback used to retrieve memories corresponding to unrecognized slots.
-     * @param requestChannel Input FMQ channel through which the client passes the request to the
-     *     service.
-     * @param resultChannel Output FMQ channel from which the client can retrieve the result of the
-     *     execution.
-     * @param burstExecutor Object which maintains a local cache of the memory pools and executes
-     *     using the cached memory pools.
-     * @param pollingTimeWindow How much time (in microseconds) the ExecutionBurstServer is allowed
-     *     to poll the FMQ before waiting on the blocking futex. Polling may result in lower
-     *     latencies at the potential cost of more power usage.
-     * @return IBurstContext Handle to the burst context.
-     */
-    static nn::GeneralResult<sp<ExecutionBurstServer>> create(
-            const sp<IBurstCallback>& callback,
-            const MQDescriptorSync<FmqRequestDatum>& requestChannel,
-            const MQDescriptorSync<FmqResultDatum>& resultChannel, nn::SharedBurst burstExecutor,
-            std::chrono::microseconds pollingTimeWindow = std::chrono::microseconds{0});
-
-    ExecutionBurstServer(PrivateConstructorTag tag, const sp<IBurstCallback>& callback,
-                         std::unique_ptr<RequestChannelReceiver> requestChannel,
-                         std::unique_ptr<ResultChannelSender> resultChannel,
-                         nn::SharedBurst burstExecutor);
-    ~ExecutionBurstServer();
-
-    // Used by the NN runtime to preemptively remove any stored memory. See
-    // IBurstContext::freeMemory for more information.
-    Return<void> freeMemory(int32_t slot) override;
-
-  private:
-    // Work loop that will continue processing execution requests until the ExecutionBurstServer
-    // object is freed.
-    void task();
-
-    nn::ExecutionResult<std::pair<hidl_vec<OutputShape>, Timing>> execute(
-            const V1_0::Request& requestWithoutPools, const std::vector<int32_t>& slotsOfPools,
-            MeasureTiming measure);
-
-    std::thread mWorker;
-    std::atomic<bool> mTeardown{false};
-    const sp<IBurstCallback> mCallback;
-    const std::unique_ptr<RequestChannelReceiver> mRequestChannelReceiver;
-    const std::unique_ptr<ResultChannelSender> mResultChannelSender;
-    const nn::SharedBurst mBurstExecutor;
-    MemoryCache mMemoryCache;
-};
-
-}  // namespace android::hardware::neuralnetworks::V1_2::utils
-
-#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_UTILS_EXECUTION_BURST_SERVER_H
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/ExecutionBurstUtils.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/ExecutionBurstUtils.h
deleted file mode 100644
index c662bc3..0000000
--- a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/ExecutionBurstUtils.h
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_UTILS_EXECUTION_BURST_UTILS_H
-#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_UTILS_EXECUTION_BURST_UTILS_H
-
-#include <android/hardware/neuralnetworks/1.0/types.h>
-#include <android/hardware/neuralnetworks/1.2/types.h>
-#include <fmq/MessageQueue.h>
-#include <hidl/MQDescriptor.h>
-#include <nnapi/Result.h>
-#include <nnapi/Types.h>
-#include <nnapi/hal/ProtectCallback.h>
-
-#include <atomic>
-#include <chrono>
-#include <memory>
-#include <tuple>
-#include <utility>
-#include <vector>
-
-namespace android::hardware::neuralnetworks::V1_2::utils {
-
-/**
- * Number of elements in the FMQ.
- */
-constexpr const size_t kExecutionBurstChannelLength = 1024;
-
-/**
- * Get how long the burst controller should poll while waiting for results to be returned.
- *
- * This time can be affected by the property "debug.nn.burst-controller-polling-window".
- *
- * @return Polling time in microseconds.
- */
-std::chrono::microseconds getBurstControllerPollingTimeWindow();
-
-/**
- * Get how long the burst server should poll while waiting for a request to be received.
- *
- * This time can be affected by the property "debug.nn.burst-server-polling-window".
- *
- * @return Polling time in microseconds.
- */
-std::chrono::microseconds getBurstServerPollingTimeWindow();
-
-/**
- * Function to serialize a request.
- *
- * @param request Request object without the pool information.
- * @param measure Whether to collect timing information for the execution.
- * @param memoryIds Slot identifiers corresponding to memory resources for the request.
- * @return Serialized FMQ request data.
- */
-std::vector<FmqRequestDatum> serialize(const V1_0::Request& request, MeasureTiming measure,
-                                       const std::vector<int32_t>& slots);
-
-/**
- * Deserialize the FMQ request data.
- *
- * The three resulting fields are the Request object (where Request::pools is empty), slot
- * identifiers (which are stand-ins for Request::pools), and whether timing information must be
- * collected for the run.
- *
- * @param data Serialized FMQ request data.
- * @return Request object if successfully deserialized, otherwise an error message.
- */
-nn::Result<std::tuple<V1_0::Request, std::vector<int32_t>, MeasureTiming>> deserialize(
-        const std::vector<FmqRequestDatum>& data);
-
-/**
- * Function to serialize results.
- *
- * @param errorStatus Status of the execution.
- * @param outputShapes Dynamic shapes of the output tensors.
- * @param timing Timing information of the execution.
- * @return Serialized FMQ result data.
- */
-std::vector<FmqResultDatum> serialize(V1_0::ErrorStatus errorStatus,
-                                      const std::vector<OutputShape>& outputShapes, Timing timing);
-
-/**
- * Deserialize the FMQ result data.
- *
- * The three resulting fields are the status of the execution, the dynamic shapes of the output
- * tensors, and the timing information of the execution.
- *
- * @param data Serialized FMQ result data.
- * @return Result object if successfully deserialized, otherwise an error message.
- */
-nn::Result<std::tuple<V1_0::ErrorStatus, std::vector<OutputShape>, Timing>> deserialize(
-        const std::vector<FmqResultDatum>& data);
-
-/**
- * RequestChannelSender is responsible for serializing the result packet of information, sending it
- * on the result channel, and signaling that the data is available.
- */
-class RequestChannelSender final : public neuralnetworks::utils::IProtectedCallback {
-    struct PrivateConstructorTag {};
-
-  public:
-    /**
-     * Create the sending end of a request channel.
-     *
-     * @param channelLength Number of elements in the FMQ.
-     * @return A pair of ResultChannelReceiver and the FMQ descriptor on successful creation,
-     *     GeneralError otherwise.
-     */
-    static nn::GeneralResult<std::pair<std::unique_ptr<RequestChannelSender>,
-                                       const MQDescriptorSync<FmqRequestDatum>*>>
-    create(size_t channelLength);
-
-    /**
-     * Send the request to the channel.
-     *
-     * @param request Request object without the pool information.
-     * @param measure Whether to collect timing information for the execution.
-     * @param slots Slot identifiers corresponding to memory resources for the request.
-     * @return An empty `Result` on successful send, otherwise an error message.
-     */
-    nn::Result<void> send(const V1_0::Request& request, MeasureTiming measure,
-                          const std::vector<int32_t>& slots);
-
-    /**
-     * Method to mark the channel as invalid, causing all future calls to RequestChannelSender::send
-     * to immediately return false without attempting to send a message across the FMQ.
-     */
-    void notifyAsDeadObject() override;
-
-    // prefer calling RequestChannelSender::send
-    nn::Result<void> sendPacket(const std::vector<FmqRequestDatum>& packet);
-
-    RequestChannelSender(PrivateConstructorTag tag, size_t channelLength);
-
-  private:
-    MessageQueue<FmqRequestDatum, kSynchronizedReadWrite> mFmqRequestChannel;
-    std::atomic<bool> mValid{true};
-};
-
-/**
- * RequestChannelReceiver is responsible for waiting on the channel until the packet is available,
- * extracting the packet from the channel, and deserializing the packet.
- *
- * Because the receiver can wait on a packet that may never come (e.g., because the sending side of
- * the packet has been closed), this object can be invalidated, unblocking the receiver.
- */
-class RequestChannelReceiver final {
-    struct PrivateConstructorTag {};
-
-  public:
-    /**
-     * Create the receiving end of a request channel.
-     *
-     * @param requestChannel Descriptor for the request channel.
-     * @param pollingTimeWindow How much time (in microseconds) the RequestChannelReceiver is
-     *     allowed to poll the FMQ before waiting on the blocking futex. Polling may result in lower
-     *     latencies at the potential cost of more power usage.
-     * @return RequestChannelReceiver on successful creation, nullptr otherwise.
-     */
-    static nn::GeneralResult<std::unique_ptr<RequestChannelReceiver>> create(
-            const MQDescriptorSync<FmqRequestDatum>& requestChannel,
-            std::chrono::microseconds pollingTimeWindow);
-
-    /**
-     * Get the request from the channel.
-     *
-     * This method will block until either:
-     * 1) The packet has been retrieved, or
-     * 2) The receiver has been invalidated
-     *
-     * @return Request object if successfully received, an appropriate message if error or if the
-     *     receiver object was invalidated.
-     */
-    nn::Result<std::tuple<V1_0::Request, std::vector<int32_t>, MeasureTiming>> getBlocking();
-
-    /**
-     * Method to mark the channel as invalid, unblocking any current or future calls to
-     * RequestChannelReceiver::getBlocking.
-     */
-    void invalidate();
-
-    RequestChannelReceiver(PrivateConstructorTag tag,
-                           const MQDescriptorSync<FmqRequestDatum>& requestChannel,
-                           std::chrono::microseconds pollingTimeWindow);
-
-  private:
-    nn::Result<std::vector<FmqRequestDatum>> getPacketBlocking();
-
-    MessageQueue<FmqRequestDatum, kSynchronizedReadWrite> mFmqRequestChannel;
-    std::atomic<bool> mTeardown{false};
-    const std::chrono::microseconds kPollingTimeWindow;
-};
-
-/**
- * ResultChannelSender is responsible for serializing the result packet of information, sending it
- * on the result channel, and signaling that the data is available.
- */
-class ResultChannelSender final {
-    struct PrivateConstructorTag {};
-
-  public:
-    /**
-     * Create the sending end of a result channel.
-     *
-     * @param resultChannel Descriptor for the result channel.
-     * @return ResultChannelSender on successful creation, nullptr otherwise.
-     */
-    static nn::GeneralResult<std::unique_ptr<ResultChannelSender>> create(
-            const MQDescriptorSync<FmqResultDatum>& resultChannel);
-
-    /**
-     * Send the result to the channel.
-     *
-     * @param errorStatus Status of the execution.
-     * @param outputShapes Dynamic shapes of the output tensors.
-     * @param timing Timing information of the execution.
-     */
-    void send(V1_0::ErrorStatus errorStatus, const std::vector<OutputShape>& outputShapes,
-              Timing timing);
-
-    // prefer calling ResultChannelSender::send
-    void sendPacket(const std::vector<FmqResultDatum>& packet);
-
-    ResultChannelSender(PrivateConstructorTag tag,
-                        const MQDescriptorSync<FmqResultDatum>& resultChannel);
-
-  private:
-    MessageQueue<FmqResultDatum, kSynchronizedReadWrite> mFmqResultChannel;
-};
-
-/**
- * ResultChannelReceiver is responsible for waiting on the channel until the packet is available,
- * extracting the packet from the channel, and deserializing the packet.
- *
- * Because the receiver can wait on a packet that may never come (e.g., because the sending side of
- * the packet has been closed), this object can be invalidated, unblocking the receiver.
- */
-class ResultChannelReceiver final : public neuralnetworks::utils::IProtectedCallback {
-    struct PrivateConstructorTag {};
-
-  public:
-    /**
-     * Create the receiving end of a result channel.
-     *
-     * @param channelLength Number of elements in the FMQ.
-     * @param pollingTimeWindow How much time (in microseconds) the ResultChannelReceiver is allowed
-     *     to poll the FMQ before waiting on the blocking futex. Polling may result in lower
-     *     latencies at the potential cost of more power usage.
-     * @return A pair of ResultChannelReceiver and the FMQ descriptor on successful creation, or
-     *     GeneralError otherwise.
-     */
-    static nn::GeneralResult<std::pair<std::unique_ptr<ResultChannelReceiver>,
-                                       const MQDescriptorSync<FmqResultDatum>*>>
-    create(size_t channelLength, std::chrono::microseconds pollingTimeWindow);
-
-    /**
-     * Get the result from the channel.
-     *
-     * This method will block until either:
-     * 1) The packet has been retrieved, or
-     * 2) The receiver has been invalidated
-     *
-     * @return Result object if successfully received, otherwise an appropriate message if error or
-     *     if the receiver object was invalidated.
-     */
-    nn::Result<std::tuple<V1_0::ErrorStatus, std::vector<OutputShape>, Timing>> getBlocking();
-
-    /**
-     * Method to mark the channel as invalid, unblocking any current or future calls to
-     * ResultChannelReceiver::getBlocking.
-     */
-    void notifyAsDeadObject() override;
-
-    // prefer calling ResultChannelReceiver::getBlocking
-    nn::Result<std::vector<FmqResultDatum>> getPacketBlocking();
-
-    ResultChannelReceiver(PrivateConstructorTag tag, size_t channelLength,
-                          std::chrono::microseconds pollingTimeWindow);
-
-  private:
-    MessageQueue<FmqResultDatum, kSynchronizedReadWrite> mFmqResultChannel;
-    std::atomic<bool> mValid{true};
-    const std::chrono::microseconds kPollingTimeWindow;
-};
-
-}  // namespace android::hardware::neuralnetworks::V1_2::utils
-
-#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_UTILS_EXECUTION_BURST_UTILS_H
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/PreparedModel.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/PreparedModel.h
index 35abd79..72a5b2f 100644
--- a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/PreparedModel.h
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/PreparedModel.h
@@ -22,8 +22,8 @@
 #include <nnapi/IPreparedModel.h>
 #include <nnapi/Result.h>
 #include <nnapi/Types.h>
+#include <nnapi/hal/1.0/ProtectCallback.h>
 #include <nnapi/hal/CommonUtils.h>
-#include <nnapi/hal/ProtectCallback.h>
 
 #include <memory>
 #include <tuple>
@@ -49,18 +49,23 @@
 
     nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
             const nn::Request& request, nn::MeasureTiming measure,
-            const nn::OptionalTimePoint& deadline,
-            const nn::OptionalDuration& loopTimeoutDuration) const override;
+            const nn::OptionalTimePoint& deadline, const nn::OptionalDuration& loopTimeoutDuration,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
 
     nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>> executeFenced(
             const nn::Request& request, const std::vector<nn::SyncFence>& waitFor,
             nn::MeasureTiming measure, const nn::OptionalTimePoint& deadline,
             const nn::OptionalDuration& loopTimeoutDuration,
-            const nn::OptionalDuration& timeoutDurationAfterFence) const override;
+            const nn::OptionalDuration& timeoutDurationAfterFence,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
 
     nn::GeneralResult<nn::SharedExecution> createReusableExecution(
             const nn::Request& request, nn::MeasureTiming measure,
-            const nn::OptionalDuration& loopTimeoutDuration) const override;
+            const nn::OptionalDuration& loopTimeoutDuration,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
 
     nn::GeneralResult<nn::SharedBurst> configureExecutionBurst() const override;
 
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Utils.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Utils.h
index 09691b6..a06f2ac 100644
--- a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Utils.h
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Utils.h
@@ -28,7 +28,6 @@
 #include <nnapi/hal/1.0/Conversions.h>
 #include <nnapi/hal/1.1/Conversions.h>
 #include <nnapi/hal/1.1/Utils.h>
-#include <nnapi/hal/HandleError.h>
 
 #include <limits>
 
@@ -40,7 +39,7 @@
 constexpr auto kDefaultMesaureTiming = MeasureTiming::NO;
 constexpr auto kNoTiming = Timing{.timeOnDevice = std::numeric_limits<uint64_t>::max(),
                                   .timeInDriver = std::numeric_limits<uint64_t>::max()};
-constexpr auto kVersion = nn::Version::ANDROID_Q;
+constexpr auto kVersion = nn::kVersionFeatureLevel3;
 
 template <typename Type>
 nn::Result<void> validate(const Type& halObject) {
@@ -61,9 +60,9 @@
 }
 
 template <typename Type>
-nn::GeneralResult<void> compliantVersion(const Type& canonical) {
-    const auto version = NN_TRY(hal::utils::makeGeneralFailure(nn::validate(canonical)));
-    if (version > kVersion) {
+nn::Result<void> compliantVersion(const Type& canonical) {
+    const auto version = NN_TRY(nn::validate(canonical));
+    if (!nn::isCompliantVersion(version, kVersion)) {
         return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion;
     }
     return {};
diff --git a/neuralnetworks/1.2/utils/src/Burst.cpp b/neuralnetworks/1.2/utils/src/Burst.cpp
new file mode 100644
index 0000000..23e8070
--- /dev/null
+++ b/neuralnetworks/1.2/utils/src/Burst.cpp
@@ -0,0 +1,470 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Burst.h"
+#include "BurstUtils.h"
+
+#include <android-base/logging.h>
+#include <android-base/thread_annotations.h>
+#include <nnapi/IBurst.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Result.h>
+#include <nnapi/TypeUtils.h>
+#include <nnapi/Types.h>
+#include <nnapi/Validation.h>
+#include <nnapi/hal/1.0/Conversions.h>
+#include <nnapi/hal/1.0/HandleError.h>
+#include <nnapi/hal/1.0/ProtectCallback.h>
+#include <nnapi/hal/CommonUtils.h>
+#include <nnapi/hal/TransferValue.h>
+
+#include <algorithm>
+#include <cstring>
+#include <limits>
+#include <memory>
+#include <string>
+#include <thread>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+#include "Callbacks.h"
+#include "Conversions.h"
+#include "Tracing.h"
+#include "Utils.h"
+
+namespace android::hardware::neuralnetworks::V1_2::utils {
+namespace {
+
+class BurstExecution final : public nn::IExecution,
+                             public std::enable_shared_from_this<BurstExecution> {
+    struct PrivateConstructorTag {};
+
+  public:
+    static nn::GeneralResult<std::shared_ptr<const BurstExecution>> create(
+            std::shared_ptr<const Burst> controller, std::vector<FmqRequestDatum> request,
+            hal::utils::RequestRelocation relocation,
+            std::vector<Burst::OptionalCacheHold> cacheHolds);
+
+    BurstExecution(PrivateConstructorTag tag, std::shared_ptr<const Burst> controller,
+                   std::vector<FmqRequestDatum> request, hal::utils::RequestRelocation relocation,
+                   std::vector<Burst::OptionalCacheHold> cacheHolds);
+
+    nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> compute(
+            const nn::OptionalTimePoint& deadline) const override;
+
+    nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>> computeFenced(
+            const std::vector<nn::SyncFence>& waitFor, const nn::OptionalTimePoint& deadline,
+            const nn::OptionalDuration& timeoutDurationAfterFence) const override;
+
+  private:
+    const std::shared_ptr<const Burst> kController;
+    const std::vector<FmqRequestDatum> kRequest;
+    const hal::utils::RequestRelocation kRelocation;
+    const std::vector<Burst::OptionalCacheHold> kCacheHolds;
+};
+
+nn::GeneralResult<sp<IBurstContext>> executionBurstResultCallback(
+        V1_0::ErrorStatus status, const sp<IBurstContext>& burstContext) {
+    HANDLE_STATUS_HIDL(status) << "IPreparedModel::configureExecutionBurst failed with status "
+                               << toString(status);
+    if (burstContext == nullptr) {
+        return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+               << "IPreparedModel::configureExecutionBurst returned nullptr for burst";
+    }
+    return burstContext;
+}
+
+nn::GeneralResult<hidl_vec<hidl_memory>> getMemoriesHelper(
+        const hidl_vec<int32_t>& slots, const std::shared_ptr<Burst::MemoryCache>& memoryCache) {
+    hidl_vec<hidl_memory> memories(slots.size());
+    for (size_t i = 0; i < slots.size(); ++i) {
+        const int32_t slot = slots[i];
+        const auto memory = NN_TRY(memoryCache->getMemory(slot));
+        memories[i] = NN_TRY(V1_0::utils::unvalidatedConvert(memory));
+        if (!memories[i].valid()) {
+            return NN_ERROR() << "memory at slot " << slot << " is invalid";
+        }
+    }
+    return memories;
+}
+
+}  // namespace
+
+// MemoryCache methods
+
+Burst::MemoryCache::MemoryCache() {
+    constexpr size_t kPreallocatedCount = 1024;
+    std::vector<int32_t> freeSlotsSpace;
+    freeSlotsSpace.reserve(kPreallocatedCount);
+    mFreeSlots = std::stack<int32_t, std::vector<int32_t>>(std::move(freeSlotsSpace));
+    mMemoryCache.reserve(kPreallocatedCount);
+    mCacheCleaner.reserve(kPreallocatedCount);
+}
+
+void Burst::MemoryCache::setBurstContext(sp<IBurstContext> burstContext) {
+    std::lock_guard guard(mMutex);
+    mBurstContext = std::move(burstContext);
+}
+
+std::pair<int32_t, Burst::MemoryCache::SharedCleanup> Burst::MemoryCache::cacheMemory(
+        const nn::SharedMemory& memory) {
+    std::unique_lock lock(mMutex);
+    base::ScopedLockAssertion lockAssert(mMutex);
+
+    // Use existing cache entry if (1) the Memory object is in the cache and (2) the cache entry is
+    // not currently being freed.
+    auto iter = mMemoryIdToSlot.find(memory);
+    while (iter != mMemoryIdToSlot.end()) {
+        const int32_t slot = iter->second;
+        if (auto cleaner = mCacheCleaner.at(slot).lock()) {
+            return std::make_pair(slot, std::move(cleaner));
+        }
+
+        // If the code reaches this point, the Memory object was in the cache, but is currently
+        // being destroyed. This code waits until the cache entry has been freed, then loops to
+        // ensure the cache entry has been freed or has been made present by another thread.
+        mCond.wait(lock);
+        iter = mMemoryIdToSlot.find(memory);
+    }
+
+    // Allocate a new cache entry.
+    const int32_t slot = allocateSlotLocked();
+    mMemoryIdToSlot[memory] = slot;
+    mMemoryCache[slot] = memory;
+
+    // Create reference-counted self-cleaning cache object.
+    auto self = weak_from_this();
+    Task cleanup = [memory, memoryCache = std::move(self)] {
+        if (const auto lock = memoryCache.lock()) {
+            lock->freeMemory(memory);
+        }
+    };
+    auto cleaner = std::make_shared<const Cleanup>(std::move(cleanup));
+    mCacheCleaner[slot] = cleaner;
+
+    return std::make_pair(slot, std::move(cleaner));
+}
+
+nn::GeneralResult<nn::SharedMemory> Burst::MemoryCache::getMemory(int32_t slot) {
+    std::lock_guard guard(mMutex);
+    if (slot < 0 || static_cast<size_t>(slot) >= mMemoryCache.size()) {
+        return NN_ERROR() << "Invalid slot: " << slot << " vs " << mMemoryCache.size();
+    }
+    return mMemoryCache[slot];
+}
+
+void Burst::MemoryCache::freeMemory(const nn::SharedMemory& memory) {
+    {
+        std::lock_guard guard(mMutex);
+        const int32_t slot = mMemoryIdToSlot.at(memory);
+        if (mBurstContext) {
+            const auto ret = mBurstContext->freeMemory(slot);
+            if (!ret.isOk()) {
+                LOG(ERROR) << "IBustContext::freeMemory failed: " << ret.description();
+            }
+        }
+        mMemoryIdToSlot.erase(memory);
+        mMemoryCache[slot] = {};
+        mCacheCleaner[slot].reset();
+        mFreeSlots.push(slot);
+    }
+    mCond.notify_all();
+}
+
+int32_t Burst::MemoryCache::allocateSlotLocked() {
+    constexpr size_t kMaxNumberOfSlots = std::numeric_limits<int32_t>::max();
+
+    // If there is a free slot, use it.
+    if (!mFreeSlots.empty()) {
+        const int32_t slot = mFreeSlots.top();
+        mFreeSlots.pop();
+        return slot;
+    }
+
+    // Use a slot for the first time.
+    CHECK_LT(mMemoryCache.size(), kMaxNumberOfSlots) << "Exceeded maximum number of slots!";
+    const int32_t slot = static_cast<int32_t>(mMemoryCache.size());
+    mMemoryCache.emplace_back();
+    mCacheCleaner.emplace_back();
+
+    return slot;
+}
+
+// ExecutionBurstCallback methods
+
+Burst::ExecutionBurstCallback::ExecutionBurstCallback(
+        const std::shared_ptr<MemoryCache>& memoryCache)
+    : kMemoryCache(memoryCache) {
+    CHECK(memoryCache != nullptr);
+}
+
+Return<void> Burst::ExecutionBurstCallback::getMemories(const hidl_vec<int32_t>& slots,
+                                                        getMemories_cb cb) {
+    const auto memoryCache = kMemoryCache.lock();
+    if (memoryCache == nullptr) {
+        LOG(ERROR) << "Burst::ExecutionBurstCallback::getMemories called after the MemoryCache has "
+                      "been freed";
+        cb(V1_0::ErrorStatus::GENERAL_FAILURE, {});
+        return Void();
+    }
+
+    const auto maybeMemories = getMemoriesHelper(slots, memoryCache);
+    if (!maybeMemories.has_value()) {
+        const auto& [message, code] = maybeMemories.error();
+        LOG(ERROR) << "Burst::ExecutionBurstCallback::getMemories failed with " << code << ": "
+                   << message;
+        cb(V1_0::ErrorStatus::INVALID_ARGUMENT, {});
+        return Void();
+    }
+
+    cb(V1_0::ErrorStatus::NONE, maybeMemories.value());
+    return Void();
+}
+
+// Burst methods
+
+nn::GeneralResult<std::shared_ptr<const Burst>> Burst::create(
+        nn::SharedPreparedModel preparedModel, const sp<V1_2::IPreparedModel>& hidlPreparedModel,
+        std::chrono::microseconds pollingTimeWindow) {
+    // check inputs
+    if (preparedModel == nullptr || hidlPreparedModel == nullptr) {
+        return NN_ERROR() << "Burst::create passed a nullptr";
+    }
+
+    // create FMQ objects
+    auto [requestChannelSender, requestChannelDescriptor] =
+            NN_TRY(RequestChannelSender::create(kExecutionBurstChannelLength));
+    auto [resultChannelReceiver, resultChannelDescriptor] =
+            NN_TRY(ResultChannelReceiver::create(kExecutionBurstChannelLength, pollingTimeWindow));
+
+    // check FMQ objects
+    CHECK(requestChannelSender != nullptr);
+    CHECK(requestChannelDescriptor != nullptr);
+    CHECK(resultChannelReceiver != nullptr);
+    CHECK(resultChannelDescriptor != nullptr);
+
+    // create memory cache
+    auto memoryCache = std::make_shared<MemoryCache>();
+
+    // create callback object
+    auto burstCallback = sp<ExecutionBurstCallback>::make(memoryCache);
+    auto cb = hal::utils::CallbackValue(executionBurstResultCallback);
+
+    // configure burst
+    const Return<void> ret = hidlPreparedModel->configureExecutionBurst(
+            burstCallback, *requestChannelDescriptor, *resultChannelDescriptor, cb);
+    HANDLE_TRANSPORT_FAILURE(ret);
+
+    auto burstContext = NN_TRY(cb.take());
+    memoryCache->setBurstContext(burstContext);
+
+    // create death handler object
+    auto deathHandler = NN_TRY(neuralnetworks::utils::DeathHandler::create(burstContext));
+    deathHandler.protectCallbackForLifetimeOfDeathHandler(requestChannelSender.get());
+    deathHandler.protectCallbackForLifetimeOfDeathHandler(resultChannelReceiver.get());
+
+    // make and return controller
+    return std::make_shared<const Burst>(
+            PrivateConstructorTag{}, std::move(preparedModel), std::move(requestChannelSender),
+            std::move(resultChannelReceiver), std::move(burstCallback), std::move(burstContext),
+            std::move(memoryCache), std::move(deathHandler));
+}
+
+Burst::Burst(PrivateConstructorTag /*tag*/, nn::SharedPreparedModel preparedModel,
+             std::unique_ptr<RequestChannelSender> requestChannelSender,
+             std::unique_ptr<ResultChannelReceiver> resultChannelReceiver,
+             sp<ExecutionBurstCallback> callback, sp<IBurstContext> burstContext,
+             std::shared_ptr<MemoryCache> memoryCache,
+             neuralnetworks::utils::DeathHandler deathHandler)
+    : kPreparedModel(std::move(preparedModel)),
+      mRequestChannelSender(std::move(requestChannelSender)),
+      mResultChannelReceiver(std::move(resultChannelReceiver)),
+      mBurstCallback(std::move(callback)),
+      mBurstContext(std::move(burstContext)),
+      mMemoryCache(std::move(memoryCache)),
+      kDeathHandler(std::move(deathHandler)) {}
+
+Burst::OptionalCacheHold Burst::cacheMemory(const nn::SharedMemory& memory) const {
+    auto [slot, hold] = mMemoryCache->cacheMemory(memory);
+    return hold;
+}
+
+nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> Burst::execute(
+        const nn::Request& request, nn::MeasureTiming measure,
+        const nn::OptionalTimePoint& deadline, const nn::OptionalDuration& loopTimeoutDuration,
+        const std::vector<nn::TokenValuePair>& /*hints*/,
+        const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
+    // This is the first point when we know an execution is occurring, so begin to collect
+    // systraces. Note that the first point we can begin collecting systraces in
+    // ExecutionBurstServer is when the RequestChannelReceiver realizes there is data in the FMQ, so
+    // ExecutionBurstServer collects systraces at different points in the code.
+    NNTRACE_RT(NNTRACE_PHASE_EXECUTION, "Burst::execute");
+
+    // if the request is valid but of a higher version than what's supported in burst execution,
+    // fall back to another execution path
+    if (!compliantVersion(request).ok()) {
+        // fallback to another execution path if the packet could not be sent
+        return kPreparedModel->execute(request, measure, deadline, loopTimeoutDuration, {}, {});
+    }
+
+    // ensure that request is ready for IPC
+    std::optional<nn::Request> maybeRequestInShared;
+    hal::utils::RequestRelocation relocation;
+    const nn::Request& requestInShared = NN_TRY(hal::utils::convertRequestFromPointerToShared(
+            &request, nn::kDefaultRequestMemoryAlignment, nn::kMinMemoryPadding,
+            &maybeRequestInShared, &relocation));
+
+    // clear pools field of request, as they will be provided via slots
+    const auto requestWithoutPools = nn::Request{
+            .inputs = requestInShared.inputs, .outputs = requestInShared.outputs, .pools = {}};
+    auto hidlRequest = NN_TRY(V1_0::utils::unvalidatedConvert(requestWithoutPools));
+    const auto hidlMeasure = NN_TRY(convert(measure));
+
+    std::vector<int32_t> slots;
+    std::vector<OptionalCacheHold> holds;
+    slots.reserve(requestInShared.pools.size());
+    holds.reserve(requestInShared.pools.size());
+    for (const auto& memoryPool : requestInShared.pools) {
+        auto [slot, hold] = mMemoryCache->cacheMemory(std::get<nn::SharedMemory>(memoryPool));
+        slots.push_back(slot);
+        holds.push_back(std::move(hold));
+    }
+
+    // send request packet
+    const auto requestPacket = serialize(hidlRequest, hidlMeasure, slots);
+    const auto fallback = [this, &request, measure, &deadline, &loopTimeoutDuration] {
+        return kPreparedModel->execute(request, measure, deadline, loopTimeoutDuration, {}, {});
+    };
+    return executeInternal(requestPacket, relocation, fallback);
+}
+
+// See IBurst::createReusableExecution for information on this method.
+nn::GeneralResult<nn::SharedExecution> Burst::createReusableExecution(
+        const nn::Request& request, nn::MeasureTiming measure,
+        const nn::OptionalDuration& loopTimeoutDuration,
+        const std::vector<nn::TokenValuePair>& /*hints*/,
+        const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
+    NNTRACE_RT(NNTRACE_PHASE_EXECUTION, "Burst::createReusableExecution");
+
+    // if the request is valid but of a higher version than what's supported in burst execution,
+    // fall back to another execution path
+    if (!compliantVersion(request).ok()) {
+        // fallback to another execution path if the packet could not be sent
+        return kPreparedModel->createReusableExecution(request, measure, loopTimeoutDuration, {},
+                                                       {});
+    }
+
+    // ensure that request is ready for IPC
+    std::optional<nn::Request> maybeRequestInShared;
+    hal::utils::RequestRelocation relocation;
+    const nn::Request& requestInShared = NN_TRY(hal::utils::convertRequestFromPointerToShared(
+            &request, nn::kDefaultRequestMemoryAlignment, nn::kMinMemoryPadding,
+            &maybeRequestInShared, &relocation));
+
+    // clear pools field of request, as they will be provided via slots
+    const auto requestWithoutPools = nn::Request{
+            .inputs = requestInShared.inputs, .outputs = requestInShared.outputs, .pools = {}};
+    auto hidlRequest = NN_TRY(V1_0::utils::unvalidatedConvert(requestWithoutPools));
+    const auto hidlMeasure = NN_TRY(convert(measure));
+
+    std::vector<int32_t> slots;
+    std::vector<OptionalCacheHold> holds;
+    slots.reserve(requestInShared.pools.size());
+    holds.reserve(requestInShared.pools.size());
+    for (const auto& memoryPool : requestInShared.pools) {
+        auto [slot, hold] = mMemoryCache->cacheMemory(std::get<nn::SharedMemory>(memoryPool));
+        slots.push_back(slot);
+        holds.push_back(std::move(hold));
+    }
+
+    const auto requestPacket = serialize(hidlRequest, hidlMeasure, slots);
+    return BurstExecution::create(shared_from_this(), std::move(requestPacket),
+                                  std::move(relocation), std::move(holds));
+}
+
+nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> Burst::executeInternal(
+        const std::vector<FmqRequestDatum>& requestPacket,
+        const hal::utils::RequestRelocation& relocation, FallbackFunction fallback) const {
+    NNTRACE_FULL(NNTRACE_LAYER_IPC, NNTRACE_PHASE_EXECUTION, "Burst::executeInternal");
+
+    // Ensure that at most one execution is in flight at any given time.
+    const bool alreadyInFlight = mExecutionInFlight.test_and_set();
+    if (alreadyInFlight) {
+        return NN_ERROR() << "IBurst already has an execution in flight";
+    }
+    const auto guard = base::make_scope_guard([this] { mExecutionInFlight.clear(); });
+
+    if (relocation.input) {
+        relocation.input->flush();
+    }
+
+    // send request packet
+    const auto sendStatus = mRequestChannelSender->sendPacket(requestPacket);
+    if (!sendStatus.ok()) {
+        // fallback to another execution path if the packet could not be sent
+        if (fallback) {
+            return fallback();
+        }
+        return NN_ERROR() << "Error sending FMQ packet: " << sendStatus.error();
+    }
+
+    // get result packet
+    const auto [status, outputShapes, timing] = NN_TRY(mResultChannelReceiver->getBlocking());
+
+    if (relocation.output) {
+        relocation.output->flush();
+    }
+    return executionCallback(status, outputShapes, timing);
+}
+
+nn::GeneralResult<std::shared_ptr<const BurstExecution>> BurstExecution::create(
+        std::shared_ptr<const Burst> controller, std::vector<FmqRequestDatum> request,
+        hal::utils::RequestRelocation relocation,
+        std::vector<Burst::OptionalCacheHold> cacheHolds) {
+    if (controller == nullptr) {
+        return NN_ERROR() << "V1_2::utils::BurstExecution::create must have non-null controller";
+    }
+
+    return std::make_shared<const BurstExecution>(PrivateConstructorTag{}, std::move(controller),
+                                                  std::move(request), std::move(relocation),
+                                                  std::move(cacheHolds));
+}
+
+BurstExecution::BurstExecution(PrivateConstructorTag /*tag*/,
+                               std::shared_ptr<const Burst> controller,
+                               std::vector<FmqRequestDatum> request,
+                               hal::utils::RequestRelocation relocation,
+                               std::vector<Burst::OptionalCacheHold> cacheHolds)
+    : kController(std::move(controller)),
+      kRequest(std::move(request)),
+      kRelocation(std::move(relocation)),
+      kCacheHolds(std::move(cacheHolds)) {}
+
+nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> BurstExecution::compute(
+        const nn::OptionalTimePoint& /*deadline*/) const {
+    return kController->executeInternal(kRequest, kRelocation, /*fallback=*/nullptr);
+}
+
+nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>>
+BurstExecution::computeFenced(const std::vector<nn::SyncFence>& /*waitFor*/,
+                              const nn::OptionalTimePoint& /*deadline*/,
+                              const nn::OptionalDuration& /*timeoutDurationAfterFence*/) const {
+    return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+           << "IExecution::computeFenced is not supported on burst object";
+}
+
+}  // namespace android::hardware::neuralnetworks::V1_2::utils
diff --git a/neuralnetworks/1.2/utils/src/BurstUtils.cpp b/neuralnetworks/1.2/utils/src/BurstUtils.cpp
new file mode 100644
index 0000000..b589c46
--- /dev/null
+++ b/neuralnetworks/1.2/utils/src/BurstUtils.cpp
@@ -0,0 +1,702 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "BurstUtils.h"
+
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware/neuralnetworks/1.1/types.h>
+#include <android/hardware/neuralnetworks/1.2/types.h>
+#include <fmq/MessageQueue.h>
+#include <hidl/MQDescriptor.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/1.0/ProtectCallback.h>
+
+#include <atomic>
+#include <chrono>
+#include <memory>
+#include <thread>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::V1_2::utils {
+namespace {
+
+constexpr V1_2::Timing kNoTiming = {std::numeric_limits<uint64_t>::max(),
+                                    std::numeric_limits<uint64_t>::max()};
+
+std::chrono::microseconds getPollingTimeWindow(const std::string& property) {
+    constexpr int32_t kDefaultPollingTimeWindow = 0;
+#ifdef NN_DEBUGGABLE
+    constexpr int32_t kMinPollingTimeWindow = 0;
+    const int32_t selectedPollingTimeWindow =
+            base::GetIntProperty(property, kDefaultPollingTimeWindow, kMinPollingTimeWindow);
+    return std::chrono::microseconds(selectedPollingTimeWindow);
+#else
+    (void)property;
+    return std::chrono::microseconds(kDefaultPollingTimeWindow);
+#endif  // NN_DEBUGGABLE
+}
+
+}  // namespace
+
+std::chrono::microseconds getBurstControllerPollingTimeWindow() {
+    return getPollingTimeWindow("debug.nn.burst-controller-polling-window");
+}
+
+std::chrono::microseconds getBurstServerPollingTimeWindow() {
+    return getPollingTimeWindow("debug.nn.burst-server-polling-window");
+}
+
+// serialize a request into a packet
+std::vector<FmqRequestDatum> serialize(const V1_0::Request& request, V1_2::MeasureTiming measure,
+                                       const std::vector<int32_t>& slots) {
+    // count how many elements need to be sent for a request
+    size_t count = 2 + request.inputs.size() + request.outputs.size() + slots.size();
+    for (const auto& input : request.inputs) {
+        count += input.dimensions.size();
+    }
+    for (const auto& output : request.outputs) {
+        count += output.dimensions.size();
+    }
+    CHECK_LE(count, std::numeric_limits<uint32_t>::max());
+
+    // create buffer to temporarily store elements
+    std::vector<FmqRequestDatum> data;
+    data.reserve(count);
+
+    // package packetInfo
+    data.emplace_back();
+    data.back().packetInformation(
+            {.packetSize = static_cast<uint32_t>(count),
+             .numberOfInputOperands = static_cast<uint32_t>(request.inputs.size()),
+             .numberOfOutputOperands = static_cast<uint32_t>(request.outputs.size()),
+             .numberOfPools = static_cast<uint32_t>(slots.size())});
+
+    // package input data
+    for (const auto& input : request.inputs) {
+        // package operand information
+        data.emplace_back();
+        data.back().inputOperandInformation(
+                {.hasNoValue = input.hasNoValue,
+                 .location = input.location,
+                 .numberOfDimensions = static_cast<uint32_t>(input.dimensions.size())});
+
+        // package operand dimensions
+        for (uint32_t dimension : input.dimensions) {
+            data.emplace_back();
+            data.back().inputOperandDimensionValue(dimension);
+        }
+    }
+
+    // package output data
+    for (const auto& output : request.outputs) {
+        // package operand information
+        data.emplace_back();
+        data.back().outputOperandInformation(
+                {.hasNoValue = output.hasNoValue,
+                 .location = output.location,
+                 .numberOfDimensions = static_cast<uint32_t>(output.dimensions.size())});
+
+        // package operand dimensions
+        for (uint32_t dimension : output.dimensions) {
+            data.emplace_back();
+            data.back().outputOperandDimensionValue(dimension);
+        }
+    }
+
+    // package pool identifier
+    for (int32_t slot : slots) {
+        data.emplace_back();
+        data.back().poolIdentifier(slot);
+    }
+
+    // package measureTiming
+    data.emplace_back();
+    data.back().measureTiming(measure);
+
+    CHECK_EQ(data.size(), count);
+
+    // return packet
+    return data;
+}
+
+// serialize result
+std::vector<FmqResultDatum> serialize(V1_0::ErrorStatus errorStatus,
+                                      const std::vector<V1_2::OutputShape>& outputShapes,
+                                      V1_2::Timing timing) {
+    // count how many elements need to be sent for a request
+    size_t count = 2 + outputShapes.size();
+    for (const auto& outputShape : outputShapes) {
+        count += outputShape.dimensions.size();
+    }
+
+    // create buffer to temporarily store elements
+    std::vector<FmqResultDatum> data;
+    data.reserve(count);
+
+    // package packetInfo
+    data.emplace_back();
+    data.back().packetInformation({.packetSize = static_cast<uint32_t>(count),
+                                   .errorStatus = errorStatus,
+                                   .numberOfOperands = static_cast<uint32_t>(outputShapes.size())});
+
+    // package output shape data
+    for (const auto& operand : outputShapes) {
+        // package operand information
+        data.emplace_back();
+        data.back().operandInformation(
+                {.isSufficient = operand.isSufficient,
+                 .numberOfDimensions = static_cast<uint32_t>(operand.dimensions.size())});
+
+        // package operand dimensions
+        for (uint32_t dimension : operand.dimensions) {
+            data.emplace_back();
+            data.back().operandDimensionValue(dimension);
+        }
+    }
+
+    // package executionTiming
+    data.emplace_back();
+    data.back().executionTiming(timing);
+
+    CHECK_EQ(data.size(), count);
+
+    // return result
+    return data;
+}
+
+// deserialize request
+nn::Result<std::tuple<V1_0::Request, std::vector<int32_t>, V1_2::MeasureTiming>> deserialize(
+        const std::vector<FmqRequestDatum>& data) {
+    using discriminator = FmqRequestDatum::hidl_discriminator;
+
+    size_t index = 0;
+
+    // validate packet information
+    if (data.size() == 0 || data[index].getDiscriminator() != discriminator::packetInformation) {
+        return NN_ERROR() << "FMQ Request packet ill-formed";
+    }
+
+    // unpackage packet information
+    const FmqRequestDatum::PacketInformation& packetInfo = data[index].packetInformation();
+    index++;
+    const uint32_t packetSize = packetInfo.packetSize;
+    const uint32_t numberOfInputOperands = packetInfo.numberOfInputOperands;
+    const uint32_t numberOfOutputOperands = packetInfo.numberOfOutputOperands;
+    const uint32_t numberOfPools = packetInfo.numberOfPools;
+
+    // verify packet size
+    if (data.size() != packetSize) {
+        return NN_ERROR() << "FMQ Request packet ill-formed";
+    }
+
+    // unpackage input operands
+    std::vector<V1_0::RequestArgument> inputs;
+    inputs.reserve(numberOfInputOperands);
+    for (size_t operand = 0; operand < numberOfInputOperands; ++operand) {
+        // validate input operand information
+        if (data[index].getDiscriminator() != discriminator::inputOperandInformation) {
+            return NN_ERROR() << "FMQ Request packet ill-formed";
+        }
+
+        // unpackage operand information
+        const FmqRequestDatum::OperandInformation& operandInfo =
+                data[index].inputOperandInformation();
+        index++;
+        const bool hasNoValue = operandInfo.hasNoValue;
+        const V1_0::DataLocation location = operandInfo.location;
+        const uint32_t numberOfDimensions = operandInfo.numberOfDimensions;
+
+        // unpackage operand dimensions
+        std::vector<uint32_t> dimensions;
+        dimensions.reserve(numberOfDimensions);
+        for (size_t i = 0; i < numberOfDimensions; ++i) {
+            // validate dimension
+            if (data[index].getDiscriminator() != discriminator::inputOperandDimensionValue) {
+                return NN_ERROR() << "FMQ Request packet ill-formed";
+            }
+
+            // unpackage dimension
+            const uint32_t dimension = data[index].inputOperandDimensionValue();
+            index++;
+
+            // store result
+            dimensions.push_back(dimension);
+        }
+
+        // store result
+        inputs.push_back(
+                {.hasNoValue = hasNoValue, .location = location, .dimensions = dimensions});
+    }
+
+    // unpackage output operands
+    std::vector<V1_0::RequestArgument> outputs;
+    outputs.reserve(numberOfOutputOperands);
+    for (size_t operand = 0; operand < numberOfOutputOperands; ++operand) {
+        // validate output operand information
+        if (data[index].getDiscriminator() != discriminator::outputOperandInformation) {
+            return NN_ERROR() << "FMQ Request packet ill-formed";
+        }
+
+        // unpackage operand information
+        const FmqRequestDatum::OperandInformation& operandInfo =
+                data[index].outputOperandInformation();
+        index++;
+        const bool hasNoValue = operandInfo.hasNoValue;
+        const V1_0::DataLocation location = operandInfo.location;
+        const uint32_t numberOfDimensions = operandInfo.numberOfDimensions;
+
+        // unpackage operand dimensions
+        std::vector<uint32_t> dimensions;
+        dimensions.reserve(numberOfDimensions);
+        for (size_t i = 0; i < numberOfDimensions; ++i) {
+            // validate dimension
+            if (data[index].getDiscriminator() != discriminator::outputOperandDimensionValue) {
+                return NN_ERROR() << "FMQ Request packet ill-formed";
+            }
+
+            // unpackage dimension
+            const uint32_t dimension = data[index].outputOperandDimensionValue();
+            index++;
+
+            // store result
+            dimensions.push_back(dimension);
+        }
+
+        // store result
+        outputs.push_back(
+                {.hasNoValue = hasNoValue, .location = location, .dimensions = dimensions});
+    }
+
+    // unpackage pools
+    std::vector<int32_t> slots;
+    slots.reserve(numberOfPools);
+    for (size_t pool = 0; pool < numberOfPools; ++pool) {
+        // validate input operand information
+        if (data[index].getDiscriminator() != discriminator::poolIdentifier) {
+            return NN_ERROR() << "FMQ Request packet ill-formed";
+        }
+
+        // unpackage operand information
+        const int32_t poolId = data[index].poolIdentifier();
+        index++;
+
+        // store result
+        slots.push_back(poolId);
+    }
+
+    // validate measureTiming
+    if (data[index].getDiscriminator() != discriminator::measureTiming) {
+        return NN_ERROR() << "FMQ Request packet ill-formed";
+    }
+
+    // unpackage measureTiming
+    const V1_2::MeasureTiming measure = data[index].measureTiming();
+    index++;
+
+    // validate packet information
+    if (index != packetSize) {
+        return NN_ERROR() << "FMQ Result packet ill-formed";
+    }
+
+    // return request
+    V1_0::Request request = {.inputs = inputs, .outputs = outputs, .pools = {}};
+    return std::make_tuple(std::move(request), std::move(slots), measure);
+}
+
+// deserialize a packet into the result
+nn::Result<std::tuple<V1_0::ErrorStatus, std::vector<V1_2::OutputShape>, V1_2::Timing>> deserialize(
+        const std::vector<FmqResultDatum>& data) {
+    using discriminator = FmqResultDatum::hidl_discriminator;
+    size_t index = 0;
+
+    // validate packet information
+    if (data.size() == 0 || data[index].getDiscriminator() != discriminator::packetInformation) {
+        return NN_ERROR() << "FMQ Result packet ill-formed";
+    }
+
+    // unpackage packet information
+    const FmqResultDatum::PacketInformation& packetInfo = data[index].packetInformation();
+    index++;
+    const uint32_t packetSize = packetInfo.packetSize;
+    const V1_0::ErrorStatus errorStatus = packetInfo.errorStatus;
+    const uint32_t numberOfOperands = packetInfo.numberOfOperands;
+
+    // verify packet size
+    if (data.size() != packetSize) {
+        return NN_ERROR() << "FMQ Result packet ill-formed";
+    }
+
+    // unpackage operands
+    std::vector<V1_2::OutputShape> outputShapes;
+    outputShapes.reserve(numberOfOperands);
+    for (size_t operand = 0; operand < numberOfOperands; ++operand) {
+        // validate operand information
+        if (data[index].getDiscriminator() != discriminator::operandInformation) {
+            return NN_ERROR() << "FMQ Result packet ill-formed";
+        }
+
+        // unpackage operand information
+        const FmqResultDatum::OperandInformation& operandInfo = data[index].operandInformation();
+        index++;
+        const bool isSufficient = operandInfo.isSufficient;
+        const uint32_t numberOfDimensions = operandInfo.numberOfDimensions;
+
+        // unpackage operand dimensions
+        std::vector<uint32_t> dimensions;
+        dimensions.reserve(numberOfDimensions);
+        for (size_t i = 0; i < numberOfDimensions; ++i) {
+            // validate dimension
+            if (data[index].getDiscriminator() != discriminator::operandDimensionValue) {
+                return NN_ERROR() << "FMQ Result packet ill-formed";
+            }
+
+            // unpackage dimension
+            const uint32_t dimension = data[index].operandDimensionValue();
+            index++;
+
+            // store result
+            dimensions.push_back(dimension);
+        }
+
+        // store result
+        outputShapes.push_back({.dimensions = dimensions, .isSufficient = isSufficient});
+    }
+
+    // validate execution timing
+    if (data[index].getDiscriminator() != discriminator::executionTiming) {
+        return NN_ERROR() << "FMQ Result packet ill-formed";
+    }
+
+    // unpackage execution timing
+    const V1_2::Timing timing = data[index].executionTiming();
+    index++;
+
+    // validate packet information
+    if (index != packetSize) {
+        return NN_ERROR() << "FMQ Result packet ill-formed";
+    }
+
+    // return result
+    return std::make_tuple(errorStatus, std::move(outputShapes), timing);
+}
+
+// RequestChannelSender methods
+
+nn::GeneralResult<
+        std::pair<std::unique_ptr<RequestChannelSender>, const MQDescriptorSync<FmqRequestDatum>*>>
+RequestChannelSender::create(size_t channelLength) {
+    auto requestChannelSender =
+            std::make_unique<RequestChannelSender>(PrivateConstructorTag{}, channelLength);
+    if (!requestChannelSender->mFmqRequestChannel.isValid()) {
+        return NN_ERROR() << "Unable to create RequestChannelSender";
+    }
+
+    const MQDescriptorSync<FmqRequestDatum>* descriptor =
+            requestChannelSender->mFmqRequestChannel.getDesc();
+    return std::make_pair(std::move(requestChannelSender), descriptor);
+}
+
+RequestChannelSender::RequestChannelSender(PrivateConstructorTag /*tag*/, size_t channelLength)
+    : mFmqRequestChannel(channelLength, /*configureEventFlagWord=*/true) {}
+
+nn::Result<void> RequestChannelSender::send(const V1_0::Request& request,
+                                            V1_2::MeasureTiming measure,
+                                            const std::vector<int32_t>& slots) {
+    const std::vector<FmqRequestDatum> serialized = serialize(request, measure, slots);
+    return sendPacket(serialized);
+}
+
+nn::Result<void> RequestChannelSender::sendPacket(const std::vector<FmqRequestDatum>& packet) {
+    if (!mValid) {
+        return NN_ERROR() << "FMQ object is invalid";
+    }
+
+    if (packet.size() > mFmqRequestChannel.availableToWrite()) {
+        return NN_ERROR()
+               << "RequestChannelSender::sendPacket -- packet size exceeds size available in FMQ";
+    }
+
+    // Always send the packet with "blocking" because this signals the futex and unblocks the
+    // consumer if it is waiting on the futex.
+    const bool success = mFmqRequestChannel.writeBlocking(packet.data(), packet.size());
+    if (!success) {
+        return NN_ERROR()
+               << "RequestChannelSender::sendPacket -- FMQ's writeBlocking returned an error";
+    }
+
+    return {};
+}
+
+void RequestChannelSender::notifyAsDeadObject() {
+    mValid = false;
+}
+
+// RequestChannelReceiver methods
+
+nn::GeneralResult<std::unique_ptr<RequestChannelReceiver>> RequestChannelReceiver::create(
+        const MQDescriptorSync<FmqRequestDatum>& requestChannel,
+        std::chrono::microseconds pollingTimeWindow) {
+    auto requestChannelReceiver = std::make_unique<RequestChannelReceiver>(
+            PrivateConstructorTag{}, requestChannel, pollingTimeWindow);
+
+    if (!requestChannelReceiver->mFmqRequestChannel.isValid()) {
+        return NN_ERROR() << "Unable to create RequestChannelReceiver";
+    }
+    if (requestChannelReceiver->mFmqRequestChannel.getEventFlagWord() == nullptr) {
+        return NN_ERROR()
+               << "RequestChannelReceiver::create was passed an MQDescriptor without an EventFlag";
+    }
+
+    return requestChannelReceiver;
+}
+
+RequestChannelReceiver::RequestChannelReceiver(
+        PrivateConstructorTag /*tag*/, const MQDescriptorSync<FmqRequestDatum>& requestChannel,
+        std::chrono::microseconds pollingTimeWindow)
+    : mFmqRequestChannel(requestChannel), kPollingTimeWindow(pollingTimeWindow) {}
+
+nn::Result<std::tuple<V1_0::Request, std::vector<int32_t>, V1_2::MeasureTiming>>
+RequestChannelReceiver::getBlocking() {
+    const auto packet = NN_TRY(getPacketBlocking());
+    return deserialize(packet);
+}
+
+void RequestChannelReceiver::invalidate() {
+    mTeardown = true;
+
+    // force unblock
+    // ExecutionBurstServer is by default waiting on a request packet. If the client process
+    // destroys its burst object, the server may still be waiting on the futex. This force unblock
+    // wakes up any thread waiting on the futex.
+    const auto data = serialize(V1_0::Request{}, V1_2::MeasureTiming::NO, {});
+    mFmqRequestChannel.writeBlocking(data.data(), data.size());
+}
+
+nn::Result<std::vector<FmqRequestDatum>> RequestChannelReceiver::getPacketBlocking() {
+    if (mTeardown) {
+        return NN_ERROR() << "FMQ object is being torn down";
+    }
+
+    // First spend time polling if results are available in FMQ instead of waiting on the futex.
+    // Polling is more responsive (yielding lower latencies), but can take up more power, so only
+    // poll for a limited period of time.
+
+    auto& getCurrentTime = std::chrono::high_resolution_clock::now;
+    const auto timeToStopPolling = getCurrentTime() + kPollingTimeWindow;
+
+    while (getCurrentTime() < timeToStopPolling) {
+        // if class is being torn down, immediately return
+        if (mTeardown.load(std::memory_order_relaxed)) {
+            return NN_ERROR() << "FMQ object is being torn down";
+        }
+
+        // Check if data is available. If it is, immediately retrieve it and return.
+        const size_t available = mFmqRequestChannel.availableToRead();
+        if (available > 0) {
+            std::vector<FmqRequestDatum> packet(available);
+            const bool success = mFmqRequestChannel.readBlocking(packet.data(), available);
+            if (!success) {
+                return NN_ERROR() << "Error receiving packet";
+            }
+            return packet;
+        }
+
+        std::this_thread::yield();
+    }
+
+    // If we get to this point, we either stopped polling because it was taking too long or polling
+    // was not allowed. Instead, perform a blocking call which uses a futex to save power.
+
+    // wait for request packet and read first element of request packet
+    FmqRequestDatum datum;
+    bool success = mFmqRequestChannel.readBlocking(&datum, 1);
+
+    // retrieve remaining elements
+    // NOTE: all of the data is already available at this point, so there's no need to do a blocking
+    // wait to wait for more data. This is known because in FMQ, all writes are published (made
+    // available) atomically. Currently, the producer always publishes the entire packet in one
+    // function call, so if the first element of the packet is available, the remaining elements are
+    // also available.
+    const size_t count = mFmqRequestChannel.availableToRead();
+    std::vector<FmqRequestDatum> packet(count + 1);
+    std::memcpy(&packet.front(), &datum, sizeof(datum));
+    success &= mFmqRequestChannel.read(packet.data() + 1, count);
+
+    // terminate loop
+    if (mTeardown) {
+        return NN_ERROR() << "FMQ object is being torn down";
+    }
+
+    // ensure packet was successfully received
+    if (!success) {
+        return NN_ERROR() << "Error receiving packet";
+    }
+
+    return packet;
+}
+
+// ResultChannelSender methods
+
+nn::GeneralResult<std::unique_ptr<ResultChannelSender>> ResultChannelSender::create(
+        const MQDescriptorSync<FmqResultDatum>& resultChannel) {
+    auto resultChannelSender =
+            std::make_unique<ResultChannelSender>(PrivateConstructorTag{}, resultChannel);
+
+    if (!resultChannelSender->mFmqResultChannel.isValid()) {
+        return NN_ERROR() << "Unable to create RequestChannelSender";
+    }
+    if (resultChannelSender->mFmqResultChannel.getEventFlagWord() == nullptr) {
+        return NN_ERROR()
+               << "ResultChannelSender::create was passed an MQDescriptor without an EventFlag";
+    }
+
+    return resultChannelSender;
+}
+
+ResultChannelSender::ResultChannelSender(PrivateConstructorTag /*tag*/,
+                                         const MQDescriptorSync<FmqResultDatum>& resultChannel)
+    : mFmqResultChannel(resultChannel) {}
+
+void ResultChannelSender::send(V1_0::ErrorStatus errorStatus,
+                               const std::vector<V1_2::OutputShape>& outputShapes,
+                               V1_2::Timing timing) {
+    const std::vector<FmqResultDatum> serialized = serialize(errorStatus, outputShapes, timing);
+    sendPacket(serialized);
+}
+
+void ResultChannelSender::sendPacket(const std::vector<FmqResultDatum>& packet) {
+    if (packet.size() > mFmqResultChannel.availableToWrite()) {
+        LOG(ERROR)
+                << "ResultChannelSender::sendPacket -- packet size exceeds size available in FMQ";
+        const std::vector<FmqResultDatum> errorPacket =
+                serialize(V1_0::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming);
+
+        // Always send the packet with "blocking" because this signals the futex and unblocks the
+        // consumer if it is waiting on the futex.
+        mFmqResultChannel.writeBlocking(errorPacket.data(), errorPacket.size());
+    } else {
+        // Always send the packet with "blocking" because this signals the futex and unblocks the
+        // consumer if it is waiting on the futex.
+        mFmqResultChannel.writeBlocking(packet.data(), packet.size());
+    }
+}
+
+// ResultChannelReceiver methods
+
+nn::GeneralResult<
+        std::pair<std::unique_ptr<ResultChannelReceiver>, const MQDescriptorSync<FmqResultDatum>*>>
+ResultChannelReceiver::create(size_t channelLength, std::chrono::microseconds pollingTimeWindow) {
+    auto resultChannelReceiver = std::make_unique<ResultChannelReceiver>(
+            PrivateConstructorTag{}, channelLength, pollingTimeWindow);
+    if (!resultChannelReceiver->mFmqResultChannel.isValid()) {
+        return NN_ERROR() << "Unable to create ResultChannelReceiver";
+    }
+
+    const MQDescriptorSync<FmqResultDatum>* descriptor =
+            resultChannelReceiver->mFmqResultChannel.getDesc();
+    return std::make_pair(std::move(resultChannelReceiver), descriptor);
+}
+
+ResultChannelReceiver::ResultChannelReceiver(PrivateConstructorTag /*tag*/, size_t channelLength,
+                                             std::chrono::microseconds pollingTimeWindow)
+    : mFmqResultChannel(channelLength, /*configureEventFlagWord=*/true),
+      kPollingTimeWindow(pollingTimeWindow) {}
+
+nn::Result<std::tuple<V1_0::ErrorStatus, std::vector<V1_2::OutputShape>, V1_2::Timing>>
+ResultChannelReceiver::getBlocking() {
+    const auto packet = NN_TRY(getPacketBlocking());
+    return deserialize(packet);
+}
+
+void ResultChannelReceiver::notifyAsDeadObject() {
+    mValid = false;
+
+    // force unblock
+    // ExecutionBurstController waits on a result packet after sending a request. If the driver
+    // containing ExecutionBurstServer crashes, the controller may be waiting on the futex. This
+    // force unblock wakes up any thread waiting on the futex.
+    const auto data = serialize(V1_0::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming);
+    mFmqResultChannel.writeBlocking(data.data(), data.size());
+}
+
+nn::Result<std::vector<FmqResultDatum>> ResultChannelReceiver::getPacketBlocking() {
+    if (!mValid) {
+        return NN_ERROR() << "FMQ object is invalid";
+    }
+
+    // First spend time polling if results are available in FMQ instead of waiting on the futex.
+    // Polling is more responsive (yielding lower latencies), but can take up more power, so only
+    // poll for a limited period of time.
+
+    auto& getCurrentTime = std::chrono::high_resolution_clock::now;
+    const auto timeToStopPolling = getCurrentTime() + kPollingTimeWindow;
+
+    while (getCurrentTime() < timeToStopPolling) {
+        // if class is being torn down, immediately return
+        if (!mValid.load(std::memory_order_relaxed)) {
+            return NN_ERROR() << "FMQ object is invalid";
+        }
+
+        // Check if data is available. If it is, immediately retrieve it and return.
+        const size_t available = mFmqResultChannel.availableToRead();
+        if (available > 0) {
+            std::vector<FmqResultDatum> packet(available);
+            const bool success = mFmqResultChannel.readBlocking(packet.data(), available);
+            if (!success) {
+                return NN_ERROR() << "Error receiving packet";
+            }
+            return packet;
+        }
+
+        std::this_thread::yield();
+    }
+
+    // If we get to this point, we either stopped polling because it was taking too long or polling
+    // was not allowed. Instead, perform a blocking call which uses a futex to save power.
+
+    // wait for result packet and read first element of result packet
+    FmqResultDatum datum;
+    bool success = mFmqResultChannel.readBlocking(&datum, 1);
+
+    // retrieve remaining elements
+    // NOTE: all of the data is already available at this point, so there's no need to do a blocking
+    // wait to wait for more data. This is known because in FMQ, all writes are published (made
+    // available) atomically. Currently, the producer always publishes the entire packet in one
+    // function call, so if the first element of the packet is available, the remaining elements are
+    // also available.
+    const size_t count = mFmqResultChannel.availableToRead();
+    std::vector<FmqResultDatum> packet(count + 1);
+    std::memcpy(&packet.front(), &datum, sizeof(datum));
+    success &= mFmqResultChannel.read(packet.data() + 1, count);
+
+    if (!mValid) {
+        return NN_ERROR() << "FMQ object is invalid";
+    }
+
+    // ensure packet was successfully received
+    if (!success) {
+        return NN_ERROR() << "Error receiving packet";
+    }
+
+    return packet;
+}
+
+}  // namespace android::hardware::neuralnetworks::V1_2::utils
diff --git a/neuralnetworks/1.2/utils/src/Callbacks.cpp b/neuralnetworks/1.2/utils/src/Callbacks.cpp
index 9f54bb1..cb61f21 100644
--- a/neuralnetworks/1.2/utils/src/Callbacks.cpp
+++ b/neuralnetworks/1.2/utils/src/Callbacks.cpp
@@ -29,10 +29,10 @@
 #include <nnapi/Types.h>
 #include <nnapi/hal/1.0/Callbacks.h>
 #include <nnapi/hal/1.0/Conversions.h>
+#include <nnapi/hal/1.0/HandleError.h>
 #include <nnapi/hal/1.0/PreparedModel.h>
+#include <nnapi/hal/1.0/ProtectCallback.h>
 #include <nnapi/hal/CommonUtils.h>
-#include <nnapi/hal/HandleError.h>
-#include <nnapi/hal/ProtectCallback.h>
 #include <nnapi/hal/TransferValue.h>
 
 #include <utility>
@@ -62,7 +62,7 @@
 
 nn::GeneralResult<nn::SharedPreparedModel> prepareModelCallback(
         V1_0::ErrorStatus status, const sp<IPreparedModel>& preparedModel) {
-    HANDLE_HAL_STATUS(status) << "model preparation failed with " << toString(status);
+    HANDLE_STATUS_HIDL(status) << "model preparation failed with " << toString(status);
     return NN_TRY(PreparedModel::create(preparedModel, /*executeSynchronously=*/true));
 }
 
@@ -74,9 +74,8 @@
         return NN_ERROR(nn::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE, std::move(canonicalOutputShapes))
                << "execution failed with " << toString(status);
     }
-    HANDLE_HAL_STATUS(status) << "execution failed with " << toString(status);
-    return hal::utils::makeExecutionFailure(
-            convertExecutionGeneralResultsHelper(outputShapes, timing));
+    HANDLE_STATUS_HIDL(status) << "execution failed with " << toString(status);
+    return convertExecutionGeneralResultsHelper(outputShapes, timing);
 }
 
 Return<void> PreparedModelCallback::notify(V1_0::ErrorStatus status,
diff --git a/neuralnetworks/1.2/utils/src/Conversions.cpp b/neuralnetworks/1.2/utils/src/Conversions.cpp
index 29945b7..78d71cf 100644
--- a/neuralnetworks/1.2/utils/src/Conversions.cpp
+++ b/neuralnetworks/1.2/utils/src/Conversions.cpp
@@ -28,7 +28,6 @@
 #include <nnapi/hal/1.0/Conversions.h>
 #include <nnapi/hal/1.1/Conversions.h>
 #include <nnapi/hal/CommonUtils.h>
-#include <nnapi/hal/HandleError.h>
 
 #include <algorithm>
 #include <functional>
@@ -120,9 +119,8 @@
             NN_TRY(unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor));
     auto operandPerformance = NN_TRY(unvalidatedConvert(capabilities.operandPerformance));
 
-    auto table = NN_TRY(hal::utils::makeGeneralFailure(
-            Capabilities::OperandPerformanceTable::create(std::move(operandPerformance)),
-            nn::ErrorStatus::GENERAL_FAILURE));
+    auto table =
+            NN_TRY(Capabilities::OperandPerformanceTable::create(std::move(operandPerformance)));
 
     return Capabilities{
             .relaxedFloat32toFloat16PerformanceScalar = relaxedFloat32toFloat16PerformanceScalar,
@@ -133,15 +131,18 @@
 
 GeneralResult<Capabilities::OperandPerformance> unvalidatedConvert(
         const hal::V1_2::Capabilities::OperandPerformance& operandPerformance) {
+    const auto type = NN_TRY(unvalidatedConvert(operandPerformance.type));
+    const auto info = NN_TRY(unvalidatedConvert(operandPerformance.info));
     return Capabilities::OperandPerformance{
-            .type = NN_TRY(unvalidatedConvert(operandPerformance.type)),
-            .info = NN_TRY(unvalidatedConvert(operandPerformance.info)),
+            .type = type,
+            .info = info,
     };
 }
 
 GeneralResult<Operation> unvalidatedConvert(const hal::V1_2::Operation& operation) {
+    const auto type = NN_TRY(unvalidatedConvert(operation.type));
     return Operation{
-            .type = NN_TRY(unvalidatedConvert(operation.type)),
+            .type = type,
             .inputs = operation.inputs,
             .outputs = operation.outputs,
     };
@@ -156,14 +157,18 @@
 }
 
 GeneralResult<Operand> unvalidatedConvert(const hal::V1_2::Operand& operand) {
+    const auto type = NN_TRY(unvalidatedConvert(operand.type));
+    const auto lifetime = NN_TRY(unvalidatedConvert(operand.lifetime));
+    const auto location = NN_TRY(unvalidatedConvert(operand.location));
+    auto extraParams = NN_TRY(unvalidatedConvert(operand.extraParams));
     return Operand{
-            .type = NN_TRY(unvalidatedConvert(operand.type)),
+            .type = type,
             .dimensions = operand.dimensions,
             .scale = operand.scale,
             .zeroPoint = operand.zeroPoint,
-            .lifetime = NN_TRY(unvalidatedConvert(operand.lifetime)),
-            .location = NN_TRY(unvalidatedConvert(operand.location)),
-            .extraParams = NN_TRY(unvalidatedConvert(operand.extraParams)),
+            .lifetime = lifetime,
+            .location = location,
+            .extraParams = std::move(extraParams),
     };
 }
 
@@ -188,7 +193,7 @@
 
     // Verify number of consumers.
     const auto numberOfConsumers =
-            NN_TRY(hal::utils::countNumberOfConsumers(model.operands.size(), operations));
+            NN_TRY(countNumberOfConsumers(model.operands.size(), operations));
     CHECK(model.operands.size() == numberOfConsumers.size());
     for (size_t i = 0; i < model.operands.size(); ++i) {
         if (model.operands[i].numberOfConsumers != numberOfConsumers[i]) {
@@ -198,25 +203,29 @@
         }
     }
 
+    auto operands = NN_TRY(unvalidatedConvert(model.operands));
     auto main = Model::Subgraph{
-            .operands = NN_TRY(unvalidatedConvert(model.operands)),
+            .operands = std::move(operands),
             .operations = std::move(operations),
             .inputIndexes = model.inputIndexes,
             .outputIndexes = model.outputIndexes,
     };
 
+    auto operandValues = NN_TRY(unvalidatedConvert(model.operandValues));
+    auto pools = NN_TRY(unvalidatedConvert(model.pools));
+    auto extensionNameToPrefix = NN_TRY(unvalidatedConvert(model.extensionNameToPrefix));
     return Model{
             .main = std::move(main),
-            .operandValues = NN_TRY(unvalidatedConvert(model.operandValues)),
-            .pools = NN_TRY(unvalidatedConvert(model.pools)),
+            .operandValues = std::move(operandValues),
+            .pools = std::move(pools),
             .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
-            .extensionNameToPrefix = NN_TRY(unvalidatedConvert(model.extensionNameToPrefix)),
+            .extensionNameToPrefix = std::move(extensionNameToPrefix),
     };
 }
 
-GeneralResult<Model::ExtensionNameAndPrefix> unvalidatedConvert(
+GeneralResult<ExtensionNameAndPrefix> unvalidatedConvert(
         const hal::V1_2::Model::ExtensionNameAndPrefix& extensionNameAndPrefix) {
-    return Model::ExtensionNameAndPrefix{
+    return ExtensionNameAndPrefix{
             .name = extensionNameAndPrefix.name,
             .prefix = extensionNameAndPrefix.prefix,
     };
@@ -250,9 +259,10 @@
 }
 
 GeneralResult<Extension> unvalidatedConvert(const hal::V1_2::Extension& extension) {
+    auto operandTypes = NN_TRY(unvalidatedConvert(extension.operandTypes));
     return Extension{
             .name = extension.name,
-            .operandTypes = NN_TRY(unvalidatedConvert(extension.operandTypes)),
+            .operandTypes = std::move(operandTypes),
     };
 }
 
@@ -265,14 +275,6 @@
     };
 }
 
-GeneralResult<SharedHandle> unvalidatedConvert(const hidl_handle& hidlHandle) {
-    if (hidlHandle.getNativeHandle() == nullptr) {
-        return nullptr;
-    }
-    auto handle = NN_TRY(hal::utils::sharedHandleFromNativeHandle(hidlHandle.getNativeHandle()));
-    return std::make_shared<const Handle>(std::move(handle));
-}
-
 GeneralResult<DeviceType> convert(const hal::V1_2::DeviceType& deviceType) {
     return validatedConvert(deviceType);
 }
@@ -335,6 +337,10 @@
     return V1_0::utils::unvalidatedConvert(operandValues);
 }
 
+nn::GeneralResult<hidl_handle> unvalidatedConvert(const nn::SharedHandle& handle) {
+    return V1_0::utils::unvalidatedConvert(handle);
+}
+
 nn::GeneralResult<hidl_memory> unvalidatedConvert(const nn::SharedMemory& memory) {
     return V1_0::utils::unvalidatedConvert(memory);
 }
@@ -412,35 +418,41 @@
 }
 
 nn::GeneralResult<Capabilities> unvalidatedConvert(const nn::Capabilities& capabilities) {
-    std::vector<nn::Capabilities::OperandPerformance> operandPerformance;
-    operandPerformance.reserve(capabilities.operandPerformance.asVector().size());
+    std::vector<nn::Capabilities::OperandPerformance> filteredOperandPerformances;
+    filteredOperandPerformances.reserve(capabilities.operandPerformance.asVector().size());
     std::copy_if(capabilities.operandPerformance.asVector().begin(),
                  capabilities.operandPerformance.asVector().end(),
-                 std::back_inserter(operandPerformance),
+                 std::back_inserter(filteredOperandPerformances),
                  [](const nn::Capabilities::OperandPerformance& operandPerformance) {
                      return compliantVersion(operandPerformance.type).has_value();
                  });
 
+    const auto relaxedFloat32toFloat16PerformanceScalar =
+            NN_TRY(unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceScalar));
+    const auto relaxedFloat32toFloat16PerformanceTensor =
+            NN_TRY(unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor));
+    auto operandPerformance = NN_TRY(unvalidatedConvert(filteredOperandPerformances));
     return Capabilities{
-            .relaxedFloat32toFloat16PerformanceScalar = NN_TRY(
-                    unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceScalar)),
-            .relaxedFloat32toFloat16PerformanceTensor = NN_TRY(
-                    unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor)),
-            .operandPerformance = NN_TRY(unvalidatedConvert(operandPerformance)),
+            .relaxedFloat32toFloat16PerformanceScalar = relaxedFloat32toFloat16PerformanceScalar,
+            .relaxedFloat32toFloat16PerformanceTensor = relaxedFloat32toFloat16PerformanceTensor,
+            .operandPerformance = std::move(operandPerformance),
     };
 }
 
 nn::GeneralResult<Capabilities::OperandPerformance> unvalidatedConvert(
         const nn::Capabilities::OperandPerformance& operandPerformance) {
+    const auto type = NN_TRY(unvalidatedConvert(operandPerformance.type));
+    const auto info = NN_TRY(unvalidatedConvert(operandPerformance.info));
     return Capabilities::OperandPerformance{
-            .type = NN_TRY(unvalidatedConvert(operandPerformance.type)),
-            .info = NN_TRY(unvalidatedConvert(operandPerformance.info)),
+            .type = type,
+            .info = info,
     };
 }
 
 nn::GeneralResult<Operation> unvalidatedConvert(const nn::Operation& operation) {
+    const auto type = NN_TRY(unvalidatedConvert(operation.type));
     return Operation{
-            .type = NN_TRY(unvalidatedConvert(operation.type)),
+            .type = type,
             .inputs = operation.inputs,
             .outputs = operation.outputs,
     };
@@ -455,15 +467,19 @@
 }
 
 nn::GeneralResult<Operand> unvalidatedConvert(const nn::Operand& operand) {
+    const auto type = NN_TRY(unvalidatedConvert(operand.type));
+    const auto lifetime = NN_TRY(unvalidatedConvert(operand.lifetime));
+    const auto location = NN_TRY(unvalidatedConvert(operand.location));
+    auto extraParams = NN_TRY(unvalidatedConvert(operand.extraParams));
     return Operand{
-            .type = NN_TRY(unvalidatedConvert(operand.type)),
+            .type = type,
             .dimensions = operand.dimensions,
             .numberOfConsumers = 0,
             .scale = operand.scale,
             .zeroPoint = operand.zeroPoint,
-            .lifetime = NN_TRY(unvalidatedConvert(operand.lifetime)),
-            .location = NN_TRY(unvalidatedConvert(operand.location)),
-            .extraParams = NN_TRY(unvalidatedConvert(operand.extraParams)),
+            .lifetime = lifetime,
+            .location = location,
+            .extraParams = std::move(extraParams),
     };
 }
 
@@ -482,26 +498,30 @@
 
     // Update number of consumers.
     const auto numberOfConsumers =
-            NN_TRY(hal::utils::countNumberOfConsumers(operands.size(), model.main.operations));
+            NN_TRY(countNumberOfConsumers(operands.size(), model.main.operations));
     CHECK(operands.size() == numberOfConsumers.size());
     for (size_t i = 0; i < operands.size(); ++i) {
         operands[i].numberOfConsumers = numberOfConsumers[i];
     }
 
+    auto operations = NN_TRY(unvalidatedConvert(model.main.operations));
+    auto operandValues = NN_TRY(unvalidatedConvert(model.operandValues));
+    auto pools = NN_TRY(unvalidatedConvert(model.pools));
+    auto extensionNameToPrefix = NN_TRY(unvalidatedConvert(model.extensionNameToPrefix));
     return Model{
             .operands = std::move(operands),
-            .operations = NN_TRY(unvalidatedConvert(model.main.operations)),
+            .operations = std::move(operations),
             .inputIndexes = model.main.inputIndexes,
             .outputIndexes = model.main.outputIndexes,
-            .operandValues = NN_TRY(unvalidatedConvert(model.operandValues)),
-            .pools = NN_TRY(unvalidatedConvert(model.pools)),
+            .operandValues = std::move(operandValues),
+            .pools = std::move(pools),
             .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
-            .extensionNameToPrefix = NN_TRY(unvalidatedConvert(model.extensionNameToPrefix)),
+            .extensionNameToPrefix = std::move(extensionNameToPrefix),
     };
 }
 
 nn::GeneralResult<Model::ExtensionNameAndPrefix> unvalidatedConvert(
-        const nn::Model::ExtensionNameAndPrefix& extensionNameAndPrefix) {
+        const nn::ExtensionNameAndPrefix& extensionNameAndPrefix) {
     return Model::ExtensionNameAndPrefix{
             .name = extensionNameAndPrefix.name,
             .prefix = extensionNameAndPrefix.prefix,
@@ -530,9 +550,10 @@
 }
 
 nn::GeneralResult<Extension> unvalidatedConvert(const nn::Extension& extension) {
+    auto operandTypes = NN_TRY(unvalidatedConvert(extension.operandTypes));
     return Extension{
             .name = extension.name,
-            .operandTypes = NN_TRY(unvalidatedConvert(extension.operandTypes)),
+            .operandTypes = std::move(operandTypes),
     };
 }
 
@@ -545,13 +566,6 @@
     };
 }
 
-nn::GeneralResult<hidl_handle> unvalidatedConvert(const nn::SharedHandle& handle) {
-    if (handle == nullptr) {
-        return {};
-    }
-    return hal::utils::hidlHandleFromSharedHandle(*handle);
-}
-
 nn::GeneralResult<DeviceType> convert(const nn::DeviceType& deviceType) {
     return validatedConvert(deviceType);
 }
diff --git a/neuralnetworks/1.2/utils/src/Device.cpp b/neuralnetworks/1.2/utils/src/Device.cpp
index 9fe0de2..3a58d2c 100644
--- a/neuralnetworks/1.2/utils/src/Device.cpp
+++ b/neuralnetworks/1.2/utils/src/Device.cpp
@@ -30,10 +30,10 @@
 #include <nnapi/OperandTypes.h>
 #include <nnapi/Result.h>
 #include <nnapi/Types.h>
+#include <nnapi/hal/1.0/HandleError.h>
+#include <nnapi/hal/1.0/ProtectCallback.h>
 #include <nnapi/hal/1.1/Conversions.h>
 #include <nnapi/hal/CommonUtils.h>
-#include <nnapi/hal/HandleError.h>
-#include <nnapi/hal/ProtectCallback.h>
 
 #include <functional>
 #include <memory>
@@ -49,31 +49,31 @@
 
 nn::GeneralResult<nn::Capabilities> capabilitiesCallback(V1_0::ErrorStatus status,
                                                          const Capabilities& capabilities) {
-    HANDLE_HAL_STATUS(status) << "getting capabilities failed with " << toString(status);
+    HANDLE_STATUS_HIDL(status) << "getting capabilities failed with " << toString(status);
     return nn::convert(capabilities);
 }
 
 nn::GeneralResult<std::string> versionStringCallback(V1_0::ErrorStatus status,
                                                      const hidl_string& versionString) {
-    HANDLE_HAL_STATUS(status) << "getVersionString failed with " << toString(status);
+    HANDLE_STATUS_HIDL(status) << "getVersionString failed with " << toString(status);
     return versionString;
 }
 
 nn::GeneralResult<nn::DeviceType> deviceTypeCallback(V1_0::ErrorStatus status,
                                                      DeviceType deviceType) {
-    HANDLE_HAL_STATUS(status) << "getDeviceType failed with " << toString(status);
+    HANDLE_STATUS_HIDL(status) << "getDeviceType failed with " << toString(status);
     return nn::convert(deviceType);
 }
 
 nn::GeneralResult<std::vector<nn::Extension>> supportedExtensionsCallback(
         V1_0::ErrorStatus status, const hidl_vec<Extension>& extensions) {
-    HANDLE_HAL_STATUS(status) << "getExtensions failed with " << toString(status);
+    HANDLE_STATUS_HIDL(status) << "getExtensions failed with " << toString(status);
     return nn::convert(extensions);
 }
 
 nn::GeneralResult<std::pair<uint32_t, uint32_t>> numberOfCacheFilesNeededCallback(
         V1_0::ErrorStatus status, uint32_t numModelCache, uint32_t numDataCache) {
-    HANDLE_HAL_STATUS(status) << "getNumberOfCacheFilesNeeded failed with " << toString(status);
+    HANDLE_STATUS_HIDL(status) << "getNumberOfCacheFilesNeeded failed with " << toString(status);
     if (numModelCache > nn::kMaxNumberOfCacheFiles) {
         return NN_ERROR() << "getNumberOfCacheFilesNeeded returned numModelCache files greater "
                              "than allowed max ("
@@ -192,7 +192,7 @@
 }
 
 nn::Version Device::getFeatureLevel() const {
-    return nn::Version::ANDROID_Q;
+    return kVersion;
 }
 
 nn::DeviceType Device::getType() const {
@@ -236,7 +236,9 @@
 nn::GeneralResult<nn::SharedPreparedModel> Device::prepareModel(
         const nn::Model& model, nn::ExecutionPreference preference, nn::Priority /*priority*/,
         nn::OptionalTimePoint /*deadline*/, const std::vector<nn::SharedHandle>& modelCache,
-        const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token) const {
+        const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token,
+        const std::vector<nn::TokenValuePair>& /*hints*/,
+        const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
     // Ensure that model is ready for IPC.
     std::optional<nn::Model> maybeModelInShared;
     const nn::Model& modelInShared =
@@ -254,7 +256,7 @@
     const auto ret = kDevice->prepareModel_1_2(hidlModel, hidlPreference, hidlModelCache,
                                                hidlDataCache, hidlToken, cb);
     const auto status = HANDLE_TRANSPORT_FAILURE(ret);
-    HANDLE_HAL_STATUS(status) << "model preparation failed with " << toString(status);
+    HANDLE_STATUS_HIDL(status) << "model preparation failed with " << toString(status);
 
     return cb->get();
 }
@@ -271,7 +273,7 @@
 
     const auto ret = kDevice->prepareModelFromCache(hidlModelCache, hidlDataCache, hidlToken, cb);
     const auto status = HANDLE_TRANSPORT_FAILURE(ret);
-    HANDLE_HAL_STATUS(status) << "model preparation from cache failed with " << toString(status);
+    HANDLE_STATUS_HIDL(status) << "model preparation from cache failed with " << toString(status);
 
     return cb->get();
 }
diff --git a/neuralnetworks/1.2/utils/src/Execution.cpp b/neuralnetworks/1.2/utils/src/Execution.cpp
index 18d1c90..320b0e1 100644
--- a/neuralnetworks/1.2/utils/src/Execution.cpp
+++ b/neuralnetworks/1.2/utils/src/Execution.cpp
@@ -29,7 +29,6 @@
 #include <nnapi/TypeUtils.h>
 #include <nnapi/Types.h>
 #include <nnapi/hal/CommonUtils.h>
-#include <nnapi/hal/HandleError.h>
 
 #include <memory>
 #include <utility>
diff --git a/neuralnetworks/1.2/utils/src/ExecutionBurstController.cpp b/neuralnetworks/1.2/utils/src/ExecutionBurstController.cpp
deleted file mode 100644
index b4b6f68..0000000
--- a/neuralnetworks/1.2/utils/src/ExecutionBurstController.cpp
+++ /dev/null
@@ -1,475 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "ExecutionBurstController"
-
-#include "ExecutionBurstController.h"
-#include "ExecutionBurstUtils.h"
-
-#include <android-base/logging.h>
-#include <android-base/thread_annotations.h>
-#include <nnapi/IBurst.h>
-#include <nnapi/IPreparedModel.h>
-#include <nnapi/Result.h>
-#include <nnapi/TypeUtils.h>
-#include <nnapi/Types.h>
-#include <nnapi/Validation.h>
-#include <nnapi/hal/1.0/Conversions.h>
-#include <nnapi/hal/CommonUtils.h>
-#include <nnapi/hal/HandleError.h>
-#include <nnapi/hal/ProtectCallback.h>
-#include <nnapi/hal/TransferValue.h>
-
-#include <algorithm>
-#include <cstring>
-#include <limits>
-#include <memory>
-#include <string>
-#include <thread>
-#include <tuple>
-#include <utility>
-#include <vector>
-
-#include "Callbacks.h"
-#include "Conversions.h"
-#include "Tracing.h"
-#include "Utils.h"
-
-namespace android::hardware::neuralnetworks::V1_2::utils {
-namespace {
-
-class BurstExecution final : public nn::IExecution,
-                             public std::enable_shared_from_this<BurstExecution> {
-    struct PrivateConstructorTag {};
-
-  public:
-    static nn::GeneralResult<std::shared_ptr<const BurstExecution>> create(
-            std::shared_ptr<const ExecutionBurstController> controller,
-            std::vector<FmqRequestDatum> request, hal::utils::RequestRelocation relocation,
-            std::vector<ExecutionBurstController::OptionalCacheHold> cacheHolds);
-
-    BurstExecution(PrivateConstructorTag tag,
-                   std::shared_ptr<const ExecutionBurstController> controller,
-                   std::vector<FmqRequestDatum> request, hal::utils::RequestRelocation relocation,
-                   std::vector<ExecutionBurstController::OptionalCacheHold> cacheHolds);
-
-    nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> compute(
-            const nn::OptionalTimePoint& deadline) const override;
-
-    nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>> computeFenced(
-            const std::vector<nn::SyncFence>& waitFor, const nn::OptionalTimePoint& deadline,
-            const nn::OptionalDuration& timeoutDurationAfterFence) const override;
-
-  private:
-    const std::shared_ptr<const ExecutionBurstController> kController;
-    const std::vector<FmqRequestDatum> kRequest;
-    const hal::utils::RequestRelocation kRelocation;
-    const std::vector<ExecutionBurstController::OptionalCacheHold> kCacheHolds;
-};
-
-nn::GeneralResult<sp<IBurstContext>> executionBurstResultCallback(
-        V1_0::ErrorStatus status, const sp<IBurstContext>& burstContext) {
-    HANDLE_HAL_STATUS(status) << "IPreparedModel::configureExecutionBurst failed with status "
-                              << toString(status);
-    if (burstContext == nullptr) {
-        return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
-               << "IPreparedModel::configureExecutionBurst returned nullptr for burst";
-    }
-    return burstContext;
-}
-
-nn::GeneralResult<hidl_vec<hidl_memory>> getMemoriesHelper(
-        const hidl_vec<int32_t>& slots,
-        const std::shared_ptr<ExecutionBurstController::MemoryCache>& memoryCache) {
-    hidl_vec<hidl_memory> memories(slots.size());
-    for (size_t i = 0; i < slots.size(); ++i) {
-        const int32_t slot = slots[i];
-        const auto memory = NN_TRY(memoryCache->getMemory(slot));
-        memories[i] = NN_TRY(V1_0::utils::unvalidatedConvert(memory));
-        if (!memories[i].valid()) {
-            return NN_ERROR() << "memory at slot " << slot << " is invalid";
-        }
-    }
-    return memories;
-}
-
-}  // namespace
-
-// MemoryCache methods
-
-ExecutionBurstController::MemoryCache::MemoryCache() {
-    constexpr size_t kPreallocatedCount = 1024;
-    std::vector<int32_t> freeSlotsSpace;
-    freeSlotsSpace.reserve(kPreallocatedCount);
-    mFreeSlots = std::stack<int32_t, std::vector<int32_t>>(std::move(freeSlotsSpace));
-    mMemoryCache.reserve(kPreallocatedCount);
-    mCacheCleaner.reserve(kPreallocatedCount);
-}
-
-void ExecutionBurstController::MemoryCache::setBurstContext(sp<IBurstContext> burstContext) {
-    std::lock_guard guard(mMutex);
-    mBurstContext = std::move(burstContext);
-}
-
-std::pair<int32_t, ExecutionBurstController::MemoryCache::SharedCleanup>
-ExecutionBurstController::MemoryCache::cacheMemory(const nn::SharedMemory& memory) {
-    std::unique_lock lock(mMutex);
-    base::ScopedLockAssertion lockAssert(mMutex);
-
-    // Use existing cache entry if (1) the Memory object is in the cache and (2) the cache entry is
-    // not currently being freed.
-    auto iter = mMemoryIdToSlot.find(memory);
-    while (iter != mMemoryIdToSlot.end()) {
-        const int32_t slot = iter->second;
-        if (auto cleaner = mCacheCleaner.at(slot).lock()) {
-            return std::make_pair(slot, std::move(cleaner));
-        }
-
-        // If the code reaches this point, the Memory object was in the cache, but is currently
-        // being destroyed. This code waits until the cache entry has been freed, then loops to
-        // ensure the cache entry has been freed or has been made present by another thread.
-        mCond.wait(lock);
-        iter = mMemoryIdToSlot.find(memory);
-    }
-
-    // Allocate a new cache entry.
-    const int32_t slot = allocateSlotLocked();
-    mMemoryIdToSlot[memory] = slot;
-    mMemoryCache[slot] = memory;
-
-    // Create reference-counted self-cleaning cache object.
-    auto self = weak_from_this();
-    Task cleanup = [memory, memoryCache = std::move(self)] {
-        if (const auto lock = memoryCache.lock()) {
-            lock->freeMemory(memory);
-        }
-    };
-    auto cleaner = std::make_shared<const Cleanup>(std::move(cleanup));
-    mCacheCleaner[slot] = cleaner;
-
-    return std::make_pair(slot, std::move(cleaner));
-}
-
-nn::GeneralResult<nn::SharedMemory> ExecutionBurstController::MemoryCache::getMemory(int32_t slot) {
-    std::lock_guard guard(mMutex);
-    if (slot < 0 || static_cast<size_t>(slot) >= mMemoryCache.size()) {
-        return NN_ERROR() << "Invalid slot: " << slot << " vs " << mMemoryCache.size();
-    }
-    return mMemoryCache[slot];
-}
-
-void ExecutionBurstController::MemoryCache::freeMemory(const nn::SharedMemory& memory) {
-    {
-        std::lock_guard guard(mMutex);
-        const int32_t slot = mMemoryIdToSlot.at(memory);
-        if (mBurstContext) {
-            mBurstContext->freeMemory(slot);
-        }
-        mMemoryIdToSlot.erase(memory);
-        mMemoryCache[slot] = {};
-        mCacheCleaner[slot].reset();
-        mFreeSlots.push(slot);
-    }
-    mCond.notify_all();
-}
-
-int32_t ExecutionBurstController::MemoryCache::allocateSlotLocked() {
-    constexpr size_t kMaxNumberOfSlots = std::numeric_limits<int32_t>::max();
-
-    // If there is a free slot, use it.
-    if (!mFreeSlots.empty()) {
-        const int32_t slot = mFreeSlots.top();
-        mFreeSlots.pop();
-        return slot;
-    }
-
-    // Use a slot for the first time.
-    CHECK_LT(mMemoryCache.size(), kMaxNumberOfSlots) << "Exceeded maximum number of slots!";
-    const int32_t slot = static_cast<int32_t>(mMemoryCache.size());
-    mMemoryCache.emplace_back();
-    mCacheCleaner.emplace_back();
-
-    return slot;
-}
-
-// ExecutionBurstCallback methods
-
-ExecutionBurstController::ExecutionBurstCallback::ExecutionBurstCallback(
-        const std::shared_ptr<MemoryCache>& memoryCache)
-    : kMemoryCache(memoryCache) {
-    CHECK(memoryCache != nullptr);
-}
-
-Return<void> ExecutionBurstController::ExecutionBurstCallback::getMemories(
-        const hidl_vec<int32_t>& slots, getMemories_cb cb) {
-    const auto memoryCache = kMemoryCache.lock();
-    if (memoryCache == nullptr) {
-        LOG(ERROR) << "ExecutionBurstController::ExecutionBurstCallback::getMemories called after "
-                      "the MemoryCache has been freed";
-        cb(V1_0::ErrorStatus::GENERAL_FAILURE, {});
-        return Void();
-    }
-
-    const auto maybeMemories = getMemoriesHelper(slots, memoryCache);
-    if (!maybeMemories.has_value()) {
-        const auto& [message, code] = maybeMemories.error();
-        LOG(ERROR) << "ExecutionBurstController::ExecutionBurstCallback::getMemories failed with "
-                   << code << ": " << message;
-        cb(V1_0::ErrorStatus::INVALID_ARGUMENT, {});
-        return Void();
-    }
-
-    cb(V1_0::ErrorStatus::NONE, maybeMemories.value());
-    return Void();
-}
-
-// ExecutionBurstController methods
-
-nn::GeneralResult<std::shared_ptr<const ExecutionBurstController>> ExecutionBurstController::create(
-        nn::SharedPreparedModel preparedModel, const sp<V1_2::IPreparedModel>& hidlPreparedModel,
-        std::chrono::microseconds pollingTimeWindow) {
-    // check inputs
-    if (preparedModel == nullptr || hidlPreparedModel == nullptr) {
-        return NN_ERROR() << "ExecutionBurstController::create passed a nullptr";
-    }
-
-    // create FMQ objects
-    auto [requestChannelSender, requestChannelDescriptor] =
-            NN_TRY(RequestChannelSender::create(kExecutionBurstChannelLength));
-    auto [resultChannelReceiver, resultChannelDescriptor] =
-            NN_TRY(ResultChannelReceiver::create(kExecutionBurstChannelLength, pollingTimeWindow));
-
-    // check FMQ objects
-    CHECK(requestChannelSender != nullptr);
-    CHECK(requestChannelDescriptor != nullptr);
-    CHECK(resultChannelReceiver != nullptr);
-    CHECK(resultChannelDescriptor != nullptr);
-
-    // create memory cache
-    auto memoryCache = std::make_shared<MemoryCache>();
-
-    // create callback object
-    auto burstCallback = sp<ExecutionBurstCallback>::make(memoryCache);
-    auto cb = hal::utils::CallbackValue(executionBurstResultCallback);
-
-    // configure burst
-    const Return<void> ret = hidlPreparedModel->configureExecutionBurst(
-            burstCallback, *requestChannelDescriptor, *resultChannelDescriptor, cb);
-    HANDLE_TRANSPORT_FAILURE(ret);
-
-    auto burstContext = NN_TRY(cb.take());
-    memoryCache->setBurstContext(burstContext);
-
-    // create death handler object
-    auto deathHandler = NN_TRY(neuralnetworks::utils::DeathHandler::create(burstContext));
-    deathHandler.protectCallbackForLifetimeOfDeathHandler(requestChannelSender.get());
-    deathHandler.protectCallbackForLifetimeOfDeathHandler(resultChannelReceiver.get());
-
-    // make and return controller
-    return std::make_shared<const ExecutionBurstController>(
-            PrivateConstructorTag{}, std::move(preparedModel), std::move(requestChannelSender),
-            std::move(resultChannelReceiver), std::move(burstCallback), std::move(burstContext),
-            std::move(memoryCache), std::move(deathHandler));
-}
-
-ExecutionBurstController::ExecutionBurstController(
-        PrivateConstructorTag /*tag*/, nn::SharedPreparedModel preparedModel,
-        std::unique_ptr<RequestChannelSender> requestChannelSender,
-        std::unique_ptr<ResultChannelReceiver> resultChannelReceiver,
-        sp<ExecutionBurstCallback> callback, sp<IBurstContext> burstContext,
-        std::shared_ptr<MemoryCache> memoryCache, neuralnetworks::utils::DeathHandler deathHandler)
-    : kPreparedModel(std::move(preparedModel)),
-      mRequestChannelSender(std::move(requestChannelSender)),
-      mResultChannelReceiver(std::move(resultChannelReceiver)),
-      mBurstCallback(std::move(callback)),
-      mBurstContext(std::move(burstContext)),
-      mMemoryCache(std::move(memoryCache)),
-      kDeathHandler(std::move(deathHandler)) {}
-
-ExecutionBurstController::OptionalCacheHold ExecutionBurstController::cacheMemory(
-        const nn::SharedMemory& memory) const {
-    auto [slot, hold] = mMemoryCache->cacheMemory(memory);
-    return hold;
-}
-
-nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>
-ExecutionBurstController::execute(const nn::Request& request, nn::MeasureTiming measure,
-                                  const nn::OptionalTimePoint& deadline,
-                                  const nn::OptionalDuration& loopTimeoutDuration) const {
-    // This is the first point when we know an execution is occurring, so begin to collect
-    // systraces. Note that the first point we can begin collecting systraces in
-    // ExecutionBurstServer is when the RequestChannelReceiver realizes there is data in the FMQ, so
-    // ExecutionBurstServer collects systraces at different points in the code.
-    NNTRACE_RT(NNTRACE_PHASE_EXECUTION, "ExecutionBurstController::execute");
-
-    // if the request is valid but of a higher version than what's supported in burst execution,
-    // fall back to another execution path
-    if (const auto version = NN_TRY(hal::utils::makeExecutionFailure(nn::validate(request)));
-        version > nn::Version::ANDROID_Q) {
-        // fallback to another execution path if the packet could not be sent
-        return kPreparedModel->execute(request, measure, deadline, loopTimeoutDuration);
-    }
-
-    // ensure that request is ready for IPC
-    std::optional<nn::Request> maybeRequestInShared;
-    hal::utils::RequestRelocation relocation;
-    const nn::Request& requestInShared =
-            NN_TRY(hal::utils::makeExecutionFailure(hal::utils::convertRequestFromPointerToShared(
-                    &request, nn::kDefaultRequestMemoryAlignment, nn::kMinMemoryPadding,
-                    &maybeRequestInShared, &relocation)));
-
-    // clear pools field of request, as they will be provided via slots
-    const auto requestWithoutPools = nn::Request{
-            .inputs = requestInShared.inputs, .outputs = requestInShared.outputs, .pools = {}};
-    auto hidlRequest = NN_TRY(
-            hal::utils::makeExecutionFailure(V1_0::utils::unvalidatedConvert(requestWithoutPools)));
-    const auto hidlMeasure = NN_TRY(hal::utils::makeExecutionFailure(convert(measure)));
-
-    std::vector<int32_t> slots;
-    std::vector<OptionalCacheHold> holds;
-    slots.reserve(requestInShared.pools.size());
-    holds.reserve(requestInShared.pools.size());
-    for (const auto& memoryPool : requestInShared.pools) {
-        auto [slot, hold] = mMemoryCache->cacheMemory(std::get<nn::SharedMemory>(memoryPool));
-        slots.push_back(slot);
-        holds.push_back(std::move(hold));
-    }
-
-    // send request packet
-    const auto requestPacket = serialize(hidlRequest, hidlMeasure, slots);
-    const auto fallback = [this, &request, measure, &deadline, &loopTimeoutDuration] {
-        return kPreparedModel->execute(request, measure, deadline, loopTimeoutDuration);
-    };
-    return executeInternal(requestPacket, relocation, fallback);
-}
-
-// See IBurst::createReusableExecution for information on this method.
-nn::GeneralResult<nn::SharedExecution> ExecutionBurstController::createReusableExecution(
-        const nn::Request& request, nn::MeasureTiming measure,
-        const nn::OptionalDuration& loopTimeoutDuration) const {
-    NNTRACE_RT(NNTRACE_PHASE_EXECUTION, "ExecutionBurstController::createReusableExecution");
-
-    // if the request is valid but of a higher version than what's supported in burst execution,
-    // fall back to another execution path
-    if (const auto version = NN_TRY(hal::utils::makeGeneralFailure(nn::validate(request)));
-        version > nn::Version::ANDROID_Q) {
-        // fallback to another execution path if the packet could not be sent
-        return kPreparedModel->createReusableExecution(request, measure, loopTimeoutDuration);
-    }
-
-    // ensure that request is ready for IPC
-    std::optional<nn::Request> maybeRequestInShared;
-    hal::utils::RequestRelocation relocation;
-    const nn::Request& requestInShared = NN_TRY(hal::utils::convertRequestFromPointerToShared(
-            &request, nn::kDefaultRequestMemoryAlignment, nn::kMinMemoryPadding,
-            &maybeRequestInShared, &relocation));
-
-    // clear pools field of request, as they will be provided via slots
-    const auto requestWithoutPools = nn::Request{
-            .inputs = requestInShared.inputs, .outputs = requestInShared.outputs, .pools = {}};
-    auto hidlRequest = NN_TRY(V1_0::utils::unvalidatedConvert(requestWithoutPools));
-    const auto hidlMeasure = NN_TRY(convert(measure));
-
-    std::vector<int32_t> slots;
-    std::vector<OptionalCacheHold> holds;
-    slots.reserve(requestInShared.pools.size());
-    holds.reserve(requestInShared.pools.size());
-    for (const auto& memoryPool : requestInShared.pools) {
-        auto [slot, hold] = mMemoryCache->cacheMemory(std::get<nn::SharedMemory>(memoryPool));
-        slots.push_back(slot);
-        holds.push_back(std::move(hold));
-    }
-
-    const auto requestPacket = serialize(hidlRequest, hidlMeasure, slots);
-    return BurstExecution::create(shared_from_this(), std::move(requestPacket),
-                                  std::move(relocation), std::move(holds));
-}
-
-nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>
-ExecutionBurstController::executeInternal(const std::vector<FmqRequestDatum>& requestPacket,
-                                          const hal::utils::RequestRelocation& relocation,
-                                          FallbackFunction fallback) const {
-    NNTRACE_FULL(NNTRACE_LAYER_IPC, NNTRACE_PHASE_EXECUTION,
-                 "ExecutionBurstController::executeInternal");
-
-    // Ensure that at most one execution is in flight at any given time.
-    const bool alreadyInFlight = mExecutionInFlight.test_and_set();
-    if (alreadyInFlight) {
-        return NN_ERROR() << "IBurst already has an execution in flight";
-    }
-    const auto guard = base::make_scope_guard([this] { mExecutionInFlight.clear(); });
-
-    if (relocation.input) {
-        relocation.input->flush();
-    }
-
-    // send request packet
-    const auto sendStatus = mRequestChannelSender->sendPacket(requestPacket);
-    if (!sendStatus.ok()) {
-        // fallback to another execution path if the packet could not be sent
-        if (fallback) {
-            return fallback();
-        }
-        return NN_ERROR() << "Error sending FMQ packet: " << sendStatus.error();
-    }
-
-    // get result packet
-    const auto [status, outputShapes, timing] =
-            NN_TRY(hal::utils::makeExecutionFailure(mResultChannelReceiver->getBlocking()));
-
-    if (relocation.output) {
-        relocation.output->flush();
-    }
-    return executionCallback(status, outputShapes, timing);
-}
-
-nn::GeneralResult<std::shared_ptr<const BurstExecution>> BurstExecution::create(
-        std::shared_ptr<const ExecutionBurstController> controller,
-        std::vector<FmqRequestDatum> request, hal::utils::RequestRelocation relocation,
-        std::vector<ExecutionBurstController::OptionalCacheHold> cacheHolds) {
-    if (controller == nullptr) {
-        return NN_ERROR() << "V1_2::utils::BurstExecution::create must have non-null controller";
-    }
-
-    return std::make_shared<const BurstExecution>(PrivateConstructorTag{}, std::move(controller),
-                                                  std::move(request), std::move(relocation),
-                                                  std::move(cacheHolds));
-}
-
-BurstExecution::BurstExecution(PrivateConstructorTag /*tag*/,
-                               std::shared_ptr<const ExecutionBurstController> controller,
-                               std::vector<FmqRequestDatum> request,
-                               hal::utils::RequestRelocation relocation,
-                               std::vector<ExecutionBurstController::OptionalCacheHold> cacheHolds)
-    : kController(std::move(controller)),
-      kRequest(std::move(request)),
-      kRelocation(std::move(relocation)),
-      kCacheHolds(std::move(cacheHolds)) {}
-
-nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> BurstExecution::compute(
-        const nn::OptionalTimePoint& /*deadline*/) const {
-    return kController->executeInternal(kRequest, kRelocation, /*fallback=*/nullptr);
-}
-
-nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>>
-BurstExecution::computeFenced(const std::vector<nn::SyncFence>& /*waitFor*/,
-                              const nn::OptionalTimePoint& /*deadline*/,
-                              const nn::OptionalDuration& /*timeoutDurationAfterFence*/) const {
-    return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
-           << "IExecution::computeFenced is not supported on burst object";
-}
-
-}  // namespace android::hardware::neuralnetworks::V1_2::utils
diff --git a/neuralnetworks/1.2/utils/src/ExecutionBurstServer.cpp b/neuralnetworks/1.2/utils/src/ExecutionBurstServer.cpp
deleted file mode 100644
index c67159e..0000000
--- a/neuralnetworks/1.2/utils/src/ExecutionBurstServer.cpp
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "ExecutionBurstServer"
-
-#include "ExecutionBurstServer.h"
-#include "Conversions.h"
-#include "ExecutionBurstUtils.h"
-
-#include <android-base/logging.h>
-#include <nnapi/IBurst.h>
-#include <nnapi/Result.h>
-#include <nnapi/TypeUtils.h>
-#include <nnapi/Types.h>
-#include <nnapi/Validation.h>
-#include <nnapi/hal/1.0/Conversions.h>
-#include <nnapi/hal/HandleError.h>
-#include <nnapi/hal/ProtectCallback.h>
-#include <nnapi/hal/TransferValue.h>
-
-#include <algorithm>
-#include <cstring>
-#include <limits>
-#include <map>
-#include <memory>
-#include <tuple>
-#include <utility>
-#include <vector>
-
-#include "Tracing.h"
-
-namespace android::hardware::neuralnetworks::V1_2::utils {
-namespace {
-
-using neuralnetworks::utils::makeExecutionFailure;
-
-constexpr V1_2::Timing kNoTiming = {std::numeric_limits<uint64_t>::max(),
-                                    std::numeric_limits<uint64_t>::max()};
-
-nn::GeneralResult<std::vector<nn::SharedMemory>> getMemoriesCallback(
-        V1_0::ErrorStatus status, const hidl_vec<hidl_memory>& memories) {
-    HANDLE_HAL_STATUS(status) << "getting burst memories failed with " << toString(status);
-    std::vector<nn::SharedMemory> canonicalMemories;
-    canonicalMemories.reserve(memories.size());
-    for (const auto& memory : memories) {
-        canonicalMemories.push_back(NN_TRY(nn::convert(memory)));
-    }
-    return canonicalMemories;
-}
-
-}  // anonymous namespace
-
-ExecutionBurstServer::MemoryCache::MemoryCache(nn::SharedBurst burstExecutor,
-                                               sp<IBurstCallback> burstCallback)
-    : kBurstExecutor(std::move(burstExecutor)), kBurstCallback(std::move(burstCallback)) {
-    CHECK(kBurstExecutor != nullptr);
-    CHECK(kBurstCallback != nullptr);
-}
-
-nn::GeneralResult<std::vector<std::pair<nn::SharedMemory, nn::IBurst::OptionalCacheHold>>>
-ExecutionBurstServer::MemoryCache::getCacheEntries(const std::vector<int32_t>& slots) {
-    std::lock_guard guard(mMutex);
-    NN_TRY(ensureCacheEntriesArePresentLocked(slots));
-
-    std::vector<std::pair<nn::SharedMemory, nn::IBurst::OptionalCacheHold>> results;
-    results.reserve(slots.size());
-    for (int32_t slot : slots) {
-        results.push_back(NN_TRY(getCacheEntryLocked(slot)));
-    }
-
-    return results;
-}
-
-nn::GeneralResult<void> ExecutionBurstServer::MemoryCache::ensureCacheEntriesArePresentLocked(
-        const std::vector<int32_t>& slots) {
-    const auto slotIsKnown = [this](int32_t slot)
-                                     REQUIRES(mMutex) { return mCache.count(slot) > 0; };
-
-    // find unique unknown slots
-    std::vector<int32_t> unknownSlots = slots;
-    std::sort(unknownSlots.begin(), unknownSlots.end());
-    auto unknownSlotsEnd = std::unique(unknownSlots.begin(), unknownSlots.end());
-    unknownSlotsEnd = std::remove_if(unknownSlots.begin(), unknownSlotsEnd, slotIsKnown);
-    unknownSlots.erase(unknownSlotsEnd, unknownSlots.end());
-
-    // quick-exit if all slots are known
-    if (unknownSlots.empty()) {
-        return {};
-    }
-
-    auto cb = neuralnetworks::utils::CallbackValue(getMemoriesCallback);
-
-    const auto ret = kBurstCallback->getMemories(unknownSlots, cb);
-    HANDLE_TRANSPORT_FAILURE(ret);
-
-    auto returnedMemories = NN_TRY(cb.take());
-
-    if (returnedMemories.size() != unknownSlots.size()) {
-        return NN_ERROR()
-               << "ExecutionBurstServer::MemoryCache::ensureCacheEntriesArePresentLocked: Error "
-                  "retrieving memories -- count mismatch between requested memories ("
-               << unknownSlots.size() << ") and returned memories (" << returnedMemories.size()
-               << ")";
-    }
-
-    // add memories to unknown slots
-    for (size_t i = 0; i < unknownSlots.size(); ++i) {
-        addCacheEntryLocked(unknownSlots[i], std::move(returnedMemories[i]));
-    }
-
-    return {};
-}
-
-nn::GeneralResult<std::pair<nn::SharedMemory, nn::IBurst::OptionalCacheHold>>
-ExecutionBurstServer::MemoryCache::getCacheEntryLocked(int32_t slot) {
-    if (const auto iter = mCache.find(slot); iter != mCache.end()) {
-        return iter->second;
-    }
-    return NN_ERROR()
-           << "ExecutionBurstServer::MemoryCache::getCacheEntryLocked failed because slot " << slot
-           << " is not present in the cache";
-}
-
-void ExecutionBurstServer::MemoryCache::addCacheEntryLocked(int32_t slot, nn::SharedMemory memory) {
-    auto hold = kBurstExecutor->cacheMemory(memory);
-    mCache.emplace(slot, std::make_pair(std::move(memory), std::move(hold)));
-}
-
-void ExecutionBurstServer::MemoryCache::removeCacheEntry(int32_t slot) {
-    std::lock_guard guard(mMutex);
-    mCache.erase(slot);
-}
-
-// ExecutionBurstServer methods
-
-nn::GeneralResult<sp<ExecutionBurstServer>> ExecutionBurstServer::create(
-        const sp<IBurstCallback>& callback, const MQDescriptorSync<FmqRequestDatum>& requestChannel,
-        const MQDescriptorSync<FmqResultDatum>& resultChannel, nn::SharedBurst burstExecutor,
-        std::chrono::microseconds pollingTimeWindow) {
-    // check inputs
-    if (callback == nullptr || burstExecutor == nullptr) {
-        return NN_ERROR() << "ExecutionBurstServer::create passed a nullptr";
-    }
-
-    // create FMQ objects
-    auto requestChannelReceiver =
-            NN_TRY(RequestChannelReceiver::create(requestChannel, pollingTimeWindow));
-    auto resultChannelSender = NN_TRY(ResultChannelSender::create(resultChannel));
-
-    // check FMQ objects
-    CHECK(requestChannelReceiver != nullptr);
-    CHECK(resultChannelSender != nullptr);
-
-    // make and return context
-    return sp<ExecutionBurstServer>::make(PrivateConstructorTag{}, callback,
-                                          std::move(requestChannelReceiver),
-                                          std::move(resultChannelSender), std::move(burstExecutor));
-}
-
-ExecutionBurstServer::ExecutionBurstServer(PrivateConstructorTag /*tag*/,
-                                           const sp<IBurstCallback>& callback,
-                                           std::unique_ptr<RequestChannelReceiver> requestChannel,
-                                           std::unique_ptr<ResultChannelSender> resultChannel,
-                                           nn::SharedBurst burstExecutor)
-    : mCallback(callback),
-      mRequestChannelReceiver(std::move(requestChannel)),
-      mResultChannelSender(std::move(resultChannel)),
-      mBurstExecutor(std::move(burstExecutor)),
-      mMemoryCache(mBurstExecutor, mCallback) {
-    // TODO: highly document the threading behavior of this class
-    mWorker = std::thread([this] { task(); });
-}
-
-ExecutionBurstServer::~ExecutionBurstServer() {
-    // set teardown flag
-    mTeardown = true;
-    mRequestChannelReceiver->invalidate();
-
-    // wait for task thread to end
-    mWorker.join();
-}
-
-Return<void> ExecutionBurstServer::freeMemory(int32_t slot) {
-    mMemoryCache.removeCacheEntry(slot);
-    return Void();
-}
-
-void ExecutionBurstServer::task() {
-    // loop until the burst object is being destroyed
-    while (!mTeardown) {
-        // receive request
-        auto arguments = mRequestChannelReceiver->getBlocking();
-
-        // if the request packet was not properly received, return a generic error and skip the
-        // execution
-        //
-        // if the burst is being torn down, skip the execution so the "task" function can end
-        if (!arguments.has_value()) {
-            if (!mTeardown) {
-                mResultChannelSender->send(V1_0::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming);
-            }
-            continue;
-        }
-
-        // unpack the arguments; types are Request, std::vector<int32_t>, and MeasureTiming,
-        // respectively
-        const auto [requestWithoutPools, slotsOfPools, measure] = std::move(arguments).value();
-
-        auto result = execute(requestWithoutPools, slotsOfPools, measure);
-
-        // return result
-        if (result.has_value()) {
-            const auto& [outputShapes, timing] = result.value();
-            mResultChannelSender->send(V1_0::ErrorStatus::NONE, outputShapes, timing);
-        } else {
-            const auto& [message, code, outputShapes] = result.error();
-            LOG(ERROR) << "IBurst::execute failed with " << code << ": " << message;
-            mResultChannelSender->send(convert(code).value(), convert(outputShapes).value(),
-                                       kNoTiming);
-        }
-    }
-}
-
-nn::ExecutionResult<std::pair<hidl_vec<OutputShape>, Timing>> ExecutionBurstServer::execute(
-        const V1_0::Request& requestWithoutPools, const std::vector<int32_t>& slotsOfPools,
-        MeasureTiming measure) {
-    NNTRACE_FULL(NNTRACE_LAYER_IPC, NNTRACE_PHASE_EXECUTION,
-                 "ExecutionBurstServer getting memory, executing, and returning results");
-
-    // ensure executor with cache has required memory
-    const auto cacheEntries =
-            NN_TRY(makeExecutionFailure(mMemoryCache.getCacheEntries(slotsOfPools)));
-
-    // convert request, populating its pools
-    // This code performs an unvalidated convert because the request object without its pools is
-    // invalid because it is incomplete. Instead, the validation is performed after the memory pools
-    // have been added to the request.
-    auto canonicalRequest =
-            NN_TRY(makeExecutionFailure(nn::unvalidatedConvert(requestWithoutPools)));
-    CHECK(canonicalRequest.pools.empty());
-    std::transform(cacheEntries.begin(), cacheEntries.end(),
-                   std::back_inserter(canonicalRequest.pools),
-                   [](const auto& cacheEntry) { return cacheEntry.first; });
-    NN_TRY(makeExecutionFailure(validate(canonicalRequest)));
-
-    nn::MeasureTiming canonicalMeasure = NN_TRY(makeExecutionFailure(nn::convert(measure)));
-
-    const auto [outputShapes, timing] =
-            NN_TRY(mBurstExecutor->execute(canonicalRequest, canonicalMeasure, {}, {}));
-
-    return std::make_pair(NN_TRY(makeExecutionFailure(convert(outputShapes))),
-                          NN_TRY(makeExecutionFailure(convert(timing))));
-}
-
-}  // namespace android::hardware::neuralnetworks::V1_2::utils
diff --git a/neuralnetworks/1.2/utils/src/ExecutionBurstUtils.cpp b/neuralnetworks/1.2/utils/src/ExecutionBurstUtils.cpp
deleted file mode 100644
index 1bdde1e..0000000
--- a/neuralnetworks/1.2/utils/src/ExecutionBurstUtils.cpp
+++ /dev/null
@@ -1,704 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "ExecutionBurstUtils"
-
-#include "ExecutionBurstUtils.h"
-
-#include <android-base/logging.h>
-#include <android-base/properties.h>
-#include <android/hardware/neuralnetworks/1.0/types.h>
-#include <android/hardware/neuralnetworks/1.1/types.h>
-#include <android/hardware/neuralnetworks/1.2/types.h>
-#include <fmq/MessageQueue.h>
-#include <hidl/MQDescriptor.h>
-#include <nnapi/Result.h>
-#include <nnapi/Types.h>
-#include <nnapi/hal/ProtectCallback.h>
-
-#include <atomic>
-#include <chrono>
-#include <memory>
-#include <thread>
-#include <tuple>
-#include <utility>
-#include <vector>
-
-namespace android::hardware::neuralnetworks::V1_2::utils {
-namespace {
-
-constexpr V1_2::Timing kNoTiming = {std::numeric_limits<uint64_t>::max(),
-                                    std::numeric_limits<uint64_t>::max()};
-
-std::chrono::microseconds getPollingTimeWindow(const std::string& property) {
-    constexpr int32_t kDefaultPollingTimeWindow = 0;
-#ifdef NN_DEBUGGABLE
-    constexpr int32_t kMinPollingTimeWindow = 0;
-    const int32_t selectedPollingTimeWindow =
-            base::GetIntProperty(property, kDefaultPollingTimeWindow, kMinPollingTimeWindow);
-    return std::chrono::microseconds(selectedPollingTimeWindow);
-#else
-    (void)property;
-    return std::chrono::microseconds(kDefaultPollingTimeWindow);
-#endif  // NN_DEBUGGABLE
-}
-
-}  // namespace
-
-std::chrono::microseconds getBurstControllerPollingTimeWindow() {
-    return getPollingTimeWindow("debug.nn.burst-controller-polling-window");
-}
-
-std::chrono::microseconds getBurstServerPollingTimeWindow() {
-    return getPollingTimeWindow("debug.nn.burst-server-polling-window");
-}
-
-// serialize a request into a packet
-std::vector<FmqRequestDatum> serialize(const V1_0::Request& request, V1_2::MeasureTiming measure,
-                                       const std::vector<int32_t>& slots) {
-    // count how many elements need to be sent for a request
-    size_t count = 2 + request.inputs.size() + request.outputs.size() + slots.size();
-    for (const auto& input : request.inputs) {
-        count += input.dimensions.size();
-    }
-    for (const auto& output : request.outputs) {
-        count += output.dimensions.size();
-    }
-    CHECK_LE(count, std::numeric_limits<uint32_t>::max());
-
-    // create buffer to temporarily store elements
-    std::vector<FmqRequestDatum> data;
-    data.reserve(count);
-
-    // package packetInfo
-    data.emplace_back();
-    data.back().packetInformation(
-            {.packetSize = static_cast<uint32_t>(count),
-             .numberOfInputOperands = static_cast<uint32_t>(request.inputs.size()),
-             .numberOfOutputOperands = static_cast<uint32_t>(request.outputs.size()),
-             .numberOfPools = static_cast<uint32_t>(slots.size())});
-
-    // package input data
-    for (const auto& input : request.inputs) {
-        // package operand information
-        data.emplace_back();
-        data.back().inputOperandInformation(
-                {.hasNoValue = input.hasNoValue,
-                 .location = input.location,
-                 .numberOfDimensions = static_cast<uint32_t>(input.dimensions.size())});
-
-        // package operand dimensions
-        for (uint32_t dimension : input.dimensions) {
-            data.emplace_back();
-            data.back().inputOperandDimensionValue(dimension);
-        }
-    }
-
-    // package output data
-    for (const auto& output : request.outputs) {
-        // package operand information
-        data.emplace_back();
-        data.back().outputOperandInformation(
-                {.hasNoValue = output.hasNoValue,
-                 .location = output.location,
-                 .numberOfDimensions = static_cast<uint32_t>(output.dimensions.size())});
-
-        // package operand dimensions
-        for (uint32_t dimension : output.dimensions) {
-            data.emplace_back();
-            data.back().outputOperandDimensionValue(dimension);
-        }
-    }
-
-    // package pool identifier
-    for (int32_t slot : slots) {
-        data.emplace_back();
-        data.back().poolIdentifier(slot);
-    }
-
-    // package measureTiming
-    data.emplace_back();
-    data.back().measureTiming(measure);
-
-    CHECK_EQ(data.size(), count);
-
-    // return packet
-    return data;
-}
-
-// serialize result
-std::vector<FmqResultDatum> serialize(V1_0::ErrorStatus errorStatus,
-                                      const std::vector<V1_2::OutputShape>& outputShapes,
-                                      V1_2::Timing timing) {
-    // count how many elements need to be sent for a request
-    size_t count = 2 + outputShapes.size();
-    for (const auto& outputShape : outputShapes) {
-        count += outputShape.dimensions.size();
-    }
-
-    // create buffer to temporarily store elements
-    std::vector<FmqResultDatum> data;
-    data.reserve(count);
-
-    // package packetInfo
-    data.emplace_back();
-    data.back().packetInformation({.packetSize = static_cast<uint32_t>(count),
-                                   .errorStatus = errorStatus,
-                                   .numberOfOperands = static_cast<uint32_t>(outputShapes.size())});
-
-    // package output shape data
-    for (const auto& operand : outputShapes) {
-        // package operand information
-        data.emplace_back();
-        data.back().operandInformation(
-                {.isSufficient = operand.isSufficient,
-                 .numberOfDimensions = static_cast<uint32_t>(operand.dimensions.size())});
-
-        // package operand dimensions
-        for (uint32_t dimension : operand.dimensions) {
-            data.emplace_back();
-            data.back().operandDimensionValue(dimension);
-        }
-    }
-
-    // package executionTiming
-    data.emplace_back();
-    data.back().executionTiming(timing);
-
-    CHECK_EQ(data.size(), count);
-
-    // return result
-    return data;
-}
-
-// deserialize request
-nn::Result<std::tuple<V1_0::Request, std::vector<int32_t>, V1_2::MeasureTiming>> deserialize(
-        const std::vector<FmqRequestDatum>& data) {
-    using discriminator = FmqRequestDatum::hidl_discriminator;
-
-    size_t index = 0;
-
-    // validate packet information
-    if (data.size() == 0 || data[index].getDiscriminator() != discriminator::packetInformation) {
-        return NN_ERROR() << "FMQ Request packet ill-formed";
-    }
-
-    // unpackage packet information
-    const FmqRequestDatum::PacketInformation& packetInfo = data[index].packetInformation();
-    index++;
-    const uint32_t packetSize = packetInfo.packetSize;
-    const uint32_t numberOfInputOperands = packetInfo.numberOfInputOperands;
-    const uint32_t numberOfOutputOperands = packetInfo.numberOfOutputOperands;
-    const uint32_t numberOfPools = packetInfo.numberOfPools;
-
-    // verify packet size
-    if (data.size() != packetSize) {
-        return NN_ERROR() << "FMQ Request packet ill-formed";
-    }
-
-    // unpackage input operands
-    std::vector<V1_0::RequestArgument> inputs;
-    inputs.reserve(numberOfInputOperands);
-    for (size_t operand = 0; operand < numberOfInputOperands; ++operand) {
-        // validate input operand information
-        if (data[index].getDiscriminator() != discriminator::inputOperandInformation) {
-            return NN_ERROR() << "FMQ Request packet ill-formed";
-        }
-
-        // unpackage operand information
-        const FmqRequestDatum::OperandInformation& operandInfo =
-                data[index].inputOperandInformation();
-        index++;
-        const bool hasNoValue = operandInfo.hasNoValue;
-        const V1_0::DataLocation location = operandInfo.location;
-        const uint32_t numberOfDimensions = operandInfo.numberOfDimensions;
-
-        // unpackage operand dimensions
-        std::vector<uint32_t> dimensions;
-        dimensions.reserve(numberOfDimensions);
-        for (size_t i = 0; i < numberOfDimensions; ++i) {
-            // validate dimension
-            if (data[index].getDiscriminator() != discriminator::inputOperandDimensionValue) {
-                return NN_ERROR() << "FMQ Request packet ill-formed";
-            }
-
-            // unpackage dimension
-            const uint32_t dimension = data[index].inputOperandDimensionValue();
-            index++;
-
-            // store result
-            dimensions.push_back(dimension);
-        }
-
-        // store result
-        inputs.push_back(
-                {.hasNoValue = hasNoValue, .location = location, .dimensions = dimensions});
-    }
-
-    // unpackage output operands
-    std::vector<V1_0::RequestArgument> outputs;
-    outputs.reserve(numberOfOutputOperands);
-    for (size_t operand = 0; operand < numberOfOutputOperands; ++operand) {
-        // validate output operand information
-        if (data[index].getDiscriminator() != discriminator::outputOperandInformation) {
-            return NN_ERROR() << "FMQ Request packet ill-formed";
-        }
-
-        // unpackage operand information
-        const FmqRequestDatum::OperandInformation& operandInfo =
-                data[index].outputOperandInformation();
-        index++;
-        const bool hasNoValue = operandInfo.hasNoValue;
-        const V1_0::DataLocation location = operandInfo.location;
-        const uint32_t numberOfDimensions = operandInfo.numberOfDimensions;
-
-        // unpackage operand dimensions
-        std::vector<uint32_t> dimensions;
-        dimensions.reserve(numberOfDimensions);
-        for (size_t i = 0; i < numberOfDimensions; ++i) {
-            // validate dimension
-            if (data[index].getDiscriminator() != discriminator::outputOperandDimensionValue) {
-                return NN_ERROR() << "FMQ Request packet ill-formed";
-            }
-
-            // unpackage dimension
-            const uint32_t dimension = data[index].outputOperandDimensionValue();
-            index++;
-
-            // store result
-            dimensions.push_back(dimension);
-        }
-
-        // store result
-        outputs.push_back(
-                {.hasNoValue = hasNoValue, .location = location, .dimensions = dimensions});
-    }
-
-    // unpackage pools
-    std::vector<int32_t> slots;
-    slots.reserve(numberOfPools);
-    for (size_t pool = 0; pool < numberOfPools; ++pool) {
-        // validate input operand information
-        if (data[index].getDiscriminator() != discriminator::poolIdentifier) {
-            return NN_ERROR() << "FMQ Request packet ill-formed";
-        }
-
-        // unpackage operand information
-        const int32_t poolId = data[index].poolIdentifier();
-        index++;
-
-        // store result
-        slots.push_back(poolId);
-    }
-
-    // validate measureTiming
-    if (data[index].getDiscriminator() != discriminator::measureTiming) {
-        return NN_ERROR() << "FMQ Request packet ill-formed";
-    }
-
-    // unpackage measureTiming
-    const V1_2::MeasureTiming measure = data[index].measureTiming();
-    index++;
-
-    // validate packet information
-    if (index != packetSize) {
-        return NN_ERROR() << "FMQ Result packet ill-formed";
-    }
-
-    // return request
-    V1_0::Request request = {.inputs = inputs, .outputs = outputs, .pools = {}};
-    return std::make_tuple(std::move(request), std::move(slots), measure);
-}
-
-// deserialize a packet into the result
-nn::Result<std::tuple<V1_0::ErrorStatus, std::vector<V1_2::OutputShape>, V1_2::Timing>> deserialize(
-        const std::vector<FmqResultDatum>& data) {
-    using discriminator = FmqResultDatum::hidl_discriminator;
-    size_t index = 0;
-
-    // validate packet information
-    if (data.size() == 0 || data[index].getDiscriminator() != discriminator::packetInformation) {
-        return NN_ERROR() << "FMQ Result packet ill-formed";
-    }
-
-    // unpackage packet information
-    const FmqResultDatum::PacketInformation& packetInfo = data[index].packetInformation();
-    index++;
-    const uint32_t packetSize = packetInfo.packetSize;
-    const V1_0::ErrorStatus errorStatus = packetInfo.errorStatus;
-    const uint32_t numberOfOperands = packetInfo.numberOfOperands;
-
-    // verify packet size
-    if (data.size() != packetSize) {
-        return NN_ERROR() << "FMQ Result packet ill-formed";
-    }
-
-    // unpackage operands
-    std::vector<V1_2::OutputShape> outputShapes;
-    outputShapes.reserve(numberOfOperands);
-    for (size_t operand = 0; operand < numberOfOperands; ++operand) {
-        // validate operand information
-        if (data[index].getDiscriminator() != discriminator::operandInformation) {
-            return NN_ERROR() << "FMQ Result packet ill-formed";
-        }
-
-        // unpackage operand information
-        const FmqResultDatum::OperandInformation& operandInfo = data[index].operandInformation();
-        index++;
-        const bool isSufficient = operandInfo.isSufficient;
-        const uint32_t numberOfDimensions = operandInfo.numberOfDimensions;
-
-        // unpackage operand dimensions
-        std::vector<uint32_t> dimensions;
-        dimensions.reserve(numberOfDimensions);
-        for (size_t i = 0; i < numberOfDimensions; ++i) {
-            // validate dimension
-            if (data[index].getDiscriminator() != discriminator::operandDimensionValue) {
-                return NN_ERROR() << "FMQ Result packet ill-formed";
-            }
-
-            // unpackage dimension
-            const uint32_t dimension = data[index].operandDimensionValue();
-            index++;
-
-            // store result
-            dimensions.push_back(dimension);
-        }
-
-        // store result
-        outputShapes.push_back({.dimensions = dimensions, .isSufficient = isSufficient});
-    }
-
-    // validate execution timing
-    if (data[index].getDiscriminator() != discriminator::executionTiming) {
-        return NN_ERROR() << "FMQ Result packet ill-formed";
-    }
-
-    // unpackage execution timing
-    const V1_2::Timing timing = data[index].executionTiming();
-    index++;
-
-    // validate packet information
-    if (index != packetSize) {
-        return NN_ERROR() << "FMQ Result packet ill-formed";
-    }
-
-    // return result
-    return std::make_tuple(errorStatus, std::move(outputShapes), timing);
-}
-
-// RequestChannelSender methods
-
-nn::GeneralResult<
-        std::pair<std::unique_ptr<RequestChannelSender>, const MQDescriptorSync<FmqRequestDatum>*>>
-RequestChannelSender::create(size_t channelLength) {
-    auto requestChannelSender =
-            std::make_unique<RequestChannelSender>(PrivateConstructorTag{}, channelLength);
-    if (!requestChannelSender->mFmqRequestChannel.isValid()) {
-        return NN_ERROR() << "Unable to create RequestChannelSender";
-    }
-
-    const MQDescriptorSync<FmqRequestDatum>* descriptor =
-            requestChannelSender->mFmqRequestChannel.getDesc();
-    return std::make_pair(std::move(requestChannelSender), descriptor);
-}
-
-RequestChannelSender::RequestChannelSender(PrivateConstructorTag /*tag*/, size_t channelLength)
-    : mFmqRequestChannel(channelLength, /*configureEventFlagWord=*/true) {}
-
-nn::Result<void> RequestChannelSender::send(const V1_0::Request& request,
-                                            V1_2::MeasureTiming measure,
-                                            const std::vector<int32_t>& slots) {
-    const std::vector<FmqRequestDatum> serialized = serialize(request, measure, slots);
-    return sendPacket(serialized);
-}
-
-nn::Result<void> RequestChannelSender::sendPacket(const std::vector<FmqRequestDatum>& packet) {
-    if (!mValid) {
-        return NN_ERROR() << "FMQ object is invalid";
-    }
-
-    if (packet.size() > mFmqRequestChannel.availableToWrite()) {
-        return NN_ERROR()
-               << "RequestChannelSender::sendPacket -- packet size exceeds size available in FMQ";
-    }
-
-    // Always send the packet with "blocking" because this signals the futex and unblocks the
-    // consumer if it is waiting on the futex.
-    const bool success = mFmqRequestChannel.writeBlocking(packet.data(), packet.size());
-    if (!success) {
-        return NN_ERROR()
-               << "RequestChannelSender::sendPacket -- FMQ's writeBlocking returned an error";
-    }
-
-    return {};
-}
-
-void RequestChannelSender::notifyAsDeadObject() {
-    mValid = false;
-}
-
-// RequestChannelReceiver methods
-
-nn::GeneralResult<std::unique_ptr<RequestChannelReceiver>> RequestChannelReceiver::create(
-        const MQDescriptorSync<FmqRequestDatum>& requestChannel,
-        std::chrono::microseconds pollingTimeWindow) {
-    auto requestChannelReceiver = std::make_unique<RequestChannelReceiver>(
-            PrivateConstructorTag{}, requestChannel, pollingTimeWindow);
-
-    if (!requestChannelReceiver->mFmqRequestChannel.isValid()) {
-        return NN_ERROR() << "Unable to create RequestChannelReceiver";
-    }
-    if (requestChannelReceiver->mFmqRequestChannel.getEventFlagWord() == nullptr) {
-        return NN_ERROR()
-               << "RequestChannelReceiver::create was passed an MQDescriptor without an EventFlag";
-    }
-
-    return requestChannelReceiver;
-}
-
-RequestChannelReceiver::RequestChannelReceiver(
-        PrivateConstructorTag /*tag*/, const MQDescriptorSync<FmqRequestDatum>& requestChannel,
-        std::chrono::microseconds pollingTimeWindow)
-    : mFmqRequestChannel(requestChannel), kPollingTimeWindow(pollingTimeWindow) {}
-
-nn::Result<std::tuple<V1_0::Request, std::vector<int32_t>, V1_2::MeasureTiming>>
-RequestChannelReceiver::getBlocking() {
-    const auto packet = NN_TRY(getPacketBlocking());
-    return deserialize(packet);
-}
-
-void RequestChannelReceiver::invalidate() {
-    mTeardown = true;
-
-    // force unblock
-    // ExecutionBurstServer is by default waiting on a request packet. If the client process
-    // destroys its burst object, the server may still be waiting on the futex. This force unblock
-    // wakes up any thread waiting on the futex.
-    const auto data = serialize(V1_0::Request{}, V1_2::MeasureTiming::NO, {});
-    mFmqRequestChannel.writeBlocking(data.data(), data.size());
-}
-
-nn::Result<std::vector<FmqRequestDatum>> RequestChannelReceiver::getPacketBlocking() {
-    if (mTeardown) {
-        return NN_ERROR() << "FMQ object is being torn down";
-    }
-
-    // First spend time polling if results are available in FMQ instead of waiting on the futex.
-    // Polling is more responsive (yielding lower latencies), but can take up more power, so only
-    // poll for a limited period of time.
-
-    auto& getCurrentTime = std::chrono::high_resolution_clock::now;
-    const auto timeToStopPolling = getCurrentTime() + kPollingTimeWindow;
-
-    while (getCurrentTime() < timeToStopPolling) {
-        // if class is being torn down, immediately return
-        if (mTeardown.load(std::memory_order_relaxed)) {
-            return NN_ERROR() << "FMQ object is being torn down";
-        }
-
-        // Check if data is available. If it is, immediately retrieve it and return.
-        const size_t available = mFmqRequestChannel.availableToRead();
-        if (available > 0) {
-            std::vector<FmqRequestDatum> packet(available);
-            const bool success = mFmqRequestChannel.readBlocking(packet.data(), available);
-            if (!success) {
-                return NN_ERROR() << "Error receiving packet";
-            }
-            return packet;
-        }
-
-        std::this_thread::yield();
-    }
-
-    // If we get to this point, we either stopped polling because it was taking too long or polling
-    // was not allowed. Instead, perform a blocking call which uses a futex to save power.
-
-    // wait for request packet and read first element of request packet
-    FmqRequestDatum datum;
-    bool success = mFmqRequestChannel.readBlocking(&datum, 1);
-
-    // retrieve remaining elements
-    // NOTE: all of the data is already available at this point, so there's no need to do a blocking
-    // wait to wait for more data. This is known because in FMQ, all writes are published (made
-    // available) atomically. Currently, the producer always publishes the entire packet in one
-    // function call, so if the first element of the packet is available, the remaining elements are
-    // also available.
-    const size_t count = mFmqRequestChannel.availableToRead();
-    std::vector<FmqRequestDatum> packet(count + 1);
-    std::memcpy(&packet.front(), &datum, sizeof(datum));
-    success &= mFmqRequestChannel.read(packet.data() + 1, count);
-
-    // terminate loop
-    if (mTeardown) {
-        return NN_ERROR() << "FMQ object is being torn down";
-    }
-
-    // ensure packet was successfully received
-    if (!success) {
-        return NN_ERROR() << "Error receiving packet";
-    }
-
-    return packet;
-}
-
-// ResultChannelSender methods
-
-nn::GeneralResult<std::unique_ptr<ResultChannelSender>> ResultChannelSender::create(
-        const MQDescriptorSync<FmqResultDatum>& resultChannel) {
-    auto resultChannelSender =
-            std::make_unique<ResultChannelSender>(PrivateConstructorTag{}, resultChannel);
-
-    if (!resultChannelSender->mFmqResultChannel.isValid()) {
-        return NN_ERROR() << "Unable to create RequestChannelSender";
-    }
-    if (resultChannelSender->mFmqResultChannel.getEventFlagWord() == nullptr) {
-        return NN_ERROR()
-               << "ResultChannelSender::create was passed an MQDescriptor without an EventFlag";
-    }
-
-    return resultChannelSender;
-}
-
-ResultChannelSender::ResultChannelSender(PrivateConstructorTag /*tag*/,
-                                         const MQDescriptorSync<FmqResultDatum>& resultChannel)
-    : mFmqResultChannel(resultChannel) {}
-
-void ResultChannelSender::send(V1_0::ErrorStatus errorStatus,
-                               const std::vector<V1_2::OutputShape>& outputShapes,
-                               V1_2::Timing timing) {
-    const std::vector<FmqResultDatum> serialized = serialize(errorStatus, outputShapes, timing);
-    sendPacket(serialized);
-}
-
-void ResultChannelSender::sendPacket(const std::vector<FmqResultDatum>& packet) {
-    if (packet.size() > mFmqResultChannel.availableToWrite()) {
-        LOG(ERROR)
-                << "ResultChannelSender::sendPacket -- packet size exceeds size available in FMQ";
-        const std::vector<FmqResultDatum> errorPacket =
-                serialize(V1_0::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming);
-
-        // Always send the packet with "blocking" because this signals the futex and unblocks the
-        // consumer if it is waiting on the futex.
-        mFmqResultChannel.writeBlocking(errorPacket.data(), errorPacket.size());
-    } else {
-        // Always send the packet with "blocking" because this signals the futex and unblocks the
-        // consumer if it is waiting on the futex.
-        mFmqResultChannel.writeBlocking(packet.data(), packet.size());
-    }
-}
-
-// ResultChannelReceiver methods
-
-nn::GeneralResult<
-        std::pair<std::unique_ptr<ResultChannelReceiver>, const MQDescriptorSync<FmqResultDatum>*>>
-ResultChannelReceiver::create(size_t channelLength, std::chrono::microseconds pollingTimeWindow) {
-    auto resultChannelReceiver = std::make_unique<ResultChannelReceiver>(
-            PrivateConstructorTag{}, channelLength, pollingTimeWindow);
-    if (!resultChannelReceiver->mFmqResultChannel.isValid()) {
-        return NN_ERROR() << "Unable to create ResultChannelReceiver";
-    }
-
-    const MQDescriptorSync<FmqResultDatum>* descriptor =
-            resultChannelReceiver->mFmqResultChannel.getDesc();
-    return std::make_pair(std::move(resultChannelReceiver), descriptor);
-}
-
-ResultChannelReceiver::ResultChannelReceiver(PrivateConstructorTag /*tag*/, size_t channelLength,
-                                             std::chrono::microseconds pollingTimeWindow)
-    : mFmqResultChannel(channelLength, /*configureEventFlagWord=*/true),
-      kPollingTimeWindow(pollingTimeWindow) {}
-
-nn::Result<std::tuple<V1_0::ErrorStatus, std::vector<V1_2::OutputShape>, V1_2::Timing>>
-ResultChannelReceiver::getBlocking() {
-    const auto packet = NN_TRY(getPacketBlocking());
-    return deserialize(packet);
-}
-
-void ResultChannelReceiver::notifyAsDeadObject() {
-    mValid = false;
-
-    // force unblock
-    // ExecutionBurstController waits on a result packet after sending a request. If the driver
-    // containing ExecutionBurstServer crashes, the controller may be waiting on the futex. This
-    // force unblock wakes up any thread waiting on the futex.
-    const auto data = serialize(V1_0::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming);
-    mFmqResultChannel.writeBlocking(data.data(), data.size());
-}
-
-nn::Result<std::vector<FmqResultDatum>> ResultChannelReceiver::getPacketBlocking() {
-    if (!mValid) {
-        return NN_ERROR() << "FMQ object is invalid";
-    }
-
-    // First spend time polling if results are available in FMQ instead of waiting on the futex.
-    // Polling is more responsive (yielding lower latencies), but can take up more power, so only
-    // poll for a limited period of time.
-
-    auto& getCurrentTime = std::chrono::high_resolution_clock::now;
-    const auto timeToStopPolling = getCurrentTime() + kPollingTimeWindow;
-
-    while (getCurrentTime() < timeToStopPolling) {
-        // if class is being torn down, immediately return
-        if (!mValid.load(std::memory_order_relaxed)) {
-            return NN_ERROR() << "FMQ object is invalid";
-        }
-
-        // Check if data is available. If it is, immediately retrieve it and return.
-        const size_t available = mFmqResultChannel.availableToRead();
-        if (available > 0) {
-            std::vector<FmqResultDatum> packet(available);
-            const bool success = mFmqResultChannel.readBlocking(packet.data(), available);
-            if (!success) {
-                return NN_ERROR() << "Error receiving packet";
-            }
-            return packet;
-        }
-
-        std::this_thread::yield();
-    }
-
-    // If we get to this point, we either stopped polling because it was taking too long or polling
-    // was not allowed. Instead, perform a blocking call which uses a futex to save power.
-
-    // wait for result packet and read first element of result packet
-    FmqResultDatum datum;
-    bool success = mFmqResultChannel.readBlocking(&datum, 1);
-
-    // retrieve remaining elements
-    // NOTE: all of the data is already available at this point, so there's no need to do a blocking
-    // wait to wait for more data. This is known because in FMQ, all writes are published (made
-    // available) atomically. Currently, the producer always publishes the entire packet in one
-    // function call, so if the first element of the packet is available, the remaining elements are
-    // also available.
-    const size_t count = mFmqResultChannel.availableToRead();
-    std::vector<FmqResultDatum> packet(count + 1);
-    std::memcpy(&packet.front(), &datum, sizeof(datum));
-    success &= mFmqResultChannel.read(packet.data() + 1, count);
-
-    if (!mValid) {
-        return NN_ERROR() << "FMQ object is invalid";
-    }
-
-    // ensure packet was successfully received
-    if (!success) {
-        return NN_ERROR() << "Error receiving packet";
-    }
-
-    return packet;
-}
-
-}  // namespace android::hardware::neuralnetworks::V1_2::utils
diff --git a/neuralnetworks/1.2/utils/src/PreparedModel.cpp b/neuralnetworks/1.2/utils/src/PreparedModel.cpp
index d0ef36e..feb3951 100644
--- a/neuralnetworks/1.2/utils/src/PreparedModel.cpp
+++ b/neuralnetworks/1.2/utils/src/PreparedModel.cpp
@@ -16,11 +16,11 @@
 
 #include "PreparedModel.h"
 
+#include "Burst.h"
+#include "BurstUtils.h"
 #include "Callbacks.h"
 #include "Conversions.h"
 #include "Execution.h"
-#include "ExecutionBurstController.h"
-#include "ExecutionBurstUtils.h"
 #include "Utils.h"
 
 #include <android/hardware/neuralnetworks/1.0/types.h>
@@ -31,9 +31,9 @@
 #include <nnapi/Result.h>
 #include <nnapi/Types.h>
 #include <nnapi/hal/1.0/Conversions.h>
+#include <nnapi/hal/1.0/HandleError.h>
+#include <nnapi/hal/1.0/ProtectCallback.h>
 #include <nnapi/hal/CommonUtils.h>
-#include <nnapi/hal/HandleError.h>
-#include <nnapi/hal/ProtectCallback.h>
 
 #include <chrono>
 #include <memory>
@@ -82,7 +82,7 @@
     const auto ret = kPreparedModel->execute_1_2(request, measure, cb);
     const auto status = HANDLE_TRANSPORT_FAILURE(ret);
     if (status != V1_0::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE) {
-        HANDLE_HAL_STATUS(status) << "execution failed with " << toString(status);
+        HANDLE_STATUS_HIDL(status) << "execution failed with " << toString(status);
     }
 
     return cb->get();
@@ -91,17 +91,18 @@
 nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> PreparedModel::execute(
         const nn::Request& request, nn::MeasureTiming measure,
         const nn::OptionalTimePoint& /*deadline*/,
-        const nn::OptionalDuration& /*loopTimeoutDuration*/) const {
+        const nn::OptionalDuration& /*loopTimeoutDuration*/,
+        const std::vector<nn::TokenValuePair>& /*hints*/,
+        const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
     // Ensure that request is ready for IPC.
     std::optional<nn::Request> maybeRequestInShared;
     hal::utils::RequestRelocation relocation;
-    const nn::Request& requestInShared =
-            NN_TRY(hal::utils::makeExecutionFailure(hal::utils::convertRequestFromPointerToShared(
-                    &request, nn::kDefaultRequestMemoryAlignment, nn::kMinMemoryPadding,
-                    &maybeRequestInShared, &relocation)));
+    const nn::Request& requestInShared = NN_TRY(hal::utils::convertRequestFromPointerToShared(
+            &request, nn::kDefaultRequestMemoryAlignment, nn::kMinMemoryPadding,
+            &maybeRequestInShared, &relocation));
 
-    const auto hidlRequest = NN_TRY(hal::utils::makeExecutionFailure(convert(requestInShared)));
-    const auto hidlMeasure = NN_TRY(hal::utils::makeExecutionFailure(convert(measure)));
+    const auto hidlRequest = NN_TRY(convert(requestInShared));
+    const auto hidlMeasure = NN_TRY(convert(measure));
 
     return executeInternal(hidlRequest, hidlMeasure, relocation);
 }
@@ -124,19 +125,22 @@
 }
 
 nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>>
-PreparedModel::executeFenced(const nn::Request& /*request*/,
-                             const std::vector<nn::SyncFence>& /*waitFor*/,
-                             nn::MeasureTiming /*measure*/,
-                             const nn::OptionalTimePoint& /*deadline*/,
-                             const nn::OptionalDuration& /*loopTimeoutDuration*/,
-                             const nn::OptionalDuration& /*timeoutDurationAfterFence*/) const {
+PreparedModel::executeFenced(
+        const nn::Request& /*request*/, const std::vector<nn::SyncFence>& /*waitFor*/,
+        nn::MeasureTiming /*measure*/, const nn::OptionalTimePoint& /*deadline*/,
+        const nn::OptionalDuration& /*loopTimeoutDuration*/,
+        const nn::OptionalDuration& /*timeoutDurationAfterFence*/,
+        const std::vector<nn::TokenValuePair>& /*hints*/,
+        const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
     return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
            << "IPreparedModel::executeFenced is not supported on 1.2 HAL service";
 }
 
 nn::GeneralResult<nn::SharedExecution> PreparedModel::createReusableExecution(
         const nn::Request& request, nn::MeasureTiming measure,
-        const nn::OptionalDuration& /*loopTimeoutDuration*/) const {
+        const nn::OptionalDuration& /*loopTimeoutDuration*/,
+        const std::vector<nn::TokenValuePair>& /*hints*/,
+        const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
     // Ensure that request is ready for IPC.
     std::optional<nn::Request> maybeRequestInShared;
     hal::utils::RequestRelocation relocation;
@@ -151,16 +155,8 @@
 }
 
 nn::GeneralResult<nn::SharedBurst> PreparedModel::configureExecutionBurst() const {
-    auto self = shared_from_this();
-    auto fallback = [preparedModel = std::move(self)](
-                            const nn::Request& request, nn::MeasureTiming measure,
-                            const nn::OptionalTimePoint& deadline,
-                            const nn::OptionalDuration& loopTimeoutDuration)
-            -> nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> {
-        return preparedModel->execute(request, measure, deadline, loopTimeoutDuration);
-    };
     const auto pollingTimeWindow = getBurstControllerPollingTimeWindow();
-    return ExecutionBurstController::create(shared_from_this(), kPreparedModel, pollingTimeWindow);
+    return Burst::create(shared_from_this(), kPreparedModel, pollingTimeWindow);
 }
 
 std::any PreparedModel::getUnderlyingResource() const {
diff --git a/neuralnetworks/1.2/utils/test/DeviceTest.cpp b/neuralnetworks/1.2/utils/test/DeviceTest.cpp
index 215d44c..0d8c141 100644
--- a/neuralnetworks/1.2/utils/test/DeviceTest.cpp
+++ b/neuralnetworks/1.2/utils/test/DeviceTest.cpp
@@ -483,7 +483,7 @@
     const auto featureLevel = device->getFeatureLevel();
 
     // verify result
-    EXPECT_EQ(featureLevel, nn::Version::ANDROID_Q);
+    EXPECT_EQ(featureLevel, nn::kVersionFeatureLevel3);
 }
 
 TEST(DeviceTest, getCachedData) {
@@ -636,7 +636,7 @@
 
     // run test
     const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
-                                             nn::Priority::DEFAULT, {}, {}, {}, {});
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_TRUE(result.has_value())
@@ -655,7 +655,7 @@
 
     // run test
     const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
-                                             nn::Priority::DEFAULT, {}, {}, {}, {});
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -673,7 +673,7 @@
 
     // run test
     const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
-                                             nn::Priority::DEFAULT, {}, {}, {}, {});
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -691,7 +691,7 @@
 
     // run test
     const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
-                                             nn::Priority::DEFAULT, {}, {}, {}, {});
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -708,7 +708,7 @@
 
     // run test
     const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
-                                             nn::Priority::DEFAULT, {}, {}, {}, {});
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -725,7 +725,7 @@
 
     // run test
     const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
-                                             nn::Priority::DEFAULT, {}, {}, {}, {});
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -746,7 +746,7 @@
 
     // run test
     const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
-                                             nn::Priority::DEFAULT, {}, {}, {}, {});
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
diff --git a/neuralnetworks/1.2/utils/test/PreparedModelTest.cpp b/neuralnetworks/1.2/utils/test/PreparedModelTest.cpp
index 5e2ad79..a5ec9d3 100644
--- a/neuralnetworks/1.2/utils/test/PreparedModelTest.cpp
+++ b/neuralnetworks/1.2/utils/test/PreparedModelTest.cpp
@@ -154,7 +154,7 @@
             .WillOnce(Invoke(makeExecuteSynchronously(V1_0::ErrorStatus::NONE, {}, kNoTiming)));
 
     // run test
-    const auto result = preparedModel->execute({}, {}, {}, {});
+    const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
 
     // verify result
     EXPECT_TRUE(result.has_value())
@@ -172,7 +172,7 @@
                     makeExecuteSynchronously(V1_0::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming)));
 
     // run test
-    const auto result = preparedModel->execute({}, {}, {}, {});
+    const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -189,7 +189,7 @@
             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
 
     // run test
-    const auto result = preparedModel->execute({}, {}, {}, {});
+    const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -206,7 +206,7 @@
             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
 
     // run test
-    const auto result = preparedModel->execute({}, {}, {}, {});
+    const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -224,7 +224,7 @@
                                                        V1_0::ErrorStatus::NONE, {}, kNoTiming)));
 
     // run test
-    const auto result = preparedModel->execute({}, {}, {}, {});
+    const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
 
     // verify result
     EXPECT_TRUE(result.has_value())
@@ -243,7 +243,7 @@
                                                        kNoTiming)));
 
     // run test
-    const auto result = preparedModel->execute({}, {}, {}, {});
+    const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -261,7 +261,7 @@
                     V1_0::ErrorStatus::NONE, V1_0::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming)));
 
     // run test
-    const auto result = preparedModel->execute({}, {}, {}, {});
+    const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -278,7 +278,7 @@
             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
 
     // run test
-    const auto result = preparedModel->execute({}, {}, {}, {});
+    const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -295,7 +295,7 @@
             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
 
     // run test
-    const auto result = preparedModel->execute({}, {}, {}, {});
+    const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -314,7 +314,7 @@
     EXPECT_CALL(*mockPreparedModel, execute_1_2(_, _, _)).Times(1).WillOnce(InvokeWithoutArgs(ret));
 
     // run test
-    const auto result = preparedModel->execute({}, {}, {}, {});
+    const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -328,7 +328,7 @@
             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
 
     // run test
-    const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
+    const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -347,7 +347,7 @@
                     Invoke(makeExecuteSynchronously(V1_0::ErrorStatus::NONE, {}, kNoTiming)));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -371,7 +371,7 @@
                     makeExecuteSynchronously(V1_0::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming)));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -392,7 +392,7 @@
             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -413,7 +413,7 @@
             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -436,7 +436,7 @@
                     V1_0::ErrorStatus::NONE, V1_0::ErrorStatus::NONE, {}, kNoTiming)));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -461,7 +461,7 @@
                                                        kNoTiming)));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -483,7 +483,7 @@
                     V1_0::ErrorStatus::NONE, V1_0::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming)));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -504,7 +504,7 @@
             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -525,7 +525,7 @@
             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -548,7 +548,7 @@
     EXPECT_CALL(*mockPreparedModel, execute_1_2(_, _, _)).Times(1).WillOnce(InvokeWithoutArgs(ret));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -566,7 +566,7 @@
             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
diff --git a/neuralnetworks/1.2/vts/OWNERS b/neuralnetworks/1.2/vts/OWNERS
deleted file mode 100644
index b5a8e1f..0000000
--- a/neuralnetworks/1.2/vts/OWNERS
+++ /dev/null
@@ -1,16 +0,0 @@
-# Neuralnetworks team
-butlermichael@google.com
-dgross@google.com
-jeanluc@google.com
-levp@google.com
-miaowang@google.com
-mikie@google.com
-mks@google.com
-pszczepaniak@google.com
-slavash@google.com
-vddang@google.com
-xusongw@google.com
-
-# VTS team
-yim@google.com
-yuexima@google.com
diff --git a/neuralnetworks/1.2/vts/functional/Android.bp b/neuralnetworks/1.2/vts/functional/Android.bp
index e313b47..2177924 100644
--- a/neuralnetworks/1.2/vts/functional/Android.bp
+++ b/neuralnetworks/1.2/vts/functional/Android.bp
@@ -44,6 +44,9 @@
 cc_test {
     name: "VtsHalNeuralnetworksV1_2TargetTest",
     defaults: ["neuralnetworks_vts_functional_defaults"],
+    tidy_timeout_srcs: [
+        "CompilationCachingTests.cpp",
+    ],
     srcs: [
         "BasicTests.cpp",
         "CompilationCachingTests.cpp",
@@ -71,7 +74,7 @@
         "libgmock",
         "libhidlmemory",
         "libneuralnetworks_generated_test_harness",
-        "libneuralnetworks_utils",
+        "libneuralnetworks_common",
     ],
     whole_static_libs: [
         "neuralnetworks_generated_V1_0_example",
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.3/types.hal b/neuralnetworks/1.3/types.hal
index a26b858..9c3bbf7 100644
--- a/neuralnetworks/1.3/types.hal
+++ b/neuralnetworks/1.3/types.hal
@@ -41,7 +41,6 @@
      * real_value = (integer_value - zeroPoint) * scale.
      */
     TENSOR_QUANT8_ASYMM_SIGNED = 14,
-
     /**
      * A reference to a subgraph.
      *
@@ -5230,7 +5229,7 @@
      * The output is calculated using the following formula:
      *
      *     h-swish(x) = x * max(0, min(6, (x + 3))) / 6
-
+     *
      * Supported tensor {@link OperandType}:
      * * {@link OperandType::TENSOR_FLOAT16}
      * * {@link OperandType::TENSOR_FLOAT32}
diff --git a/neuralnetworks/1.3/utils/Android.bp b/neuralnetworks/1.3/utils/Android.bp
index 28c036a..05413e6 100644
--- a/neuralnetworks/1.3/utils/Android.bp
+++ b/neuralnetworks/1.3/utils/Android.bp
@@ -31,26 +31,26 @@
     export_include_dirs: ["include"],
     cflags: ["-Wthread-safety"],
     static_libs: [
+        "android.hardware.neuralnetworks@1.0",
+        "android.hardware.neuralnetworks@1.1",
+        "android.hardware.neuralnetworks@1.2",
+        "android.hardware.neuralnetworks@1.3",
+        "libfmq",
         "neuralnetworks_types",
         "neuralnetworks_utils_hal_common",
         "neuralnetworks_utils_hal_1_0",
         "neuralnetworks_utils_hal_1_1",
         "neuralnetworks_utils_hal_1_2",
     ],
-    shared_libs: [
-        "android.hardware.neuralnetworks@1.0",
-        "android.hardware.neuralnetworks@1.1",
-        "android.hardware.neuralnetworks@1.2",
-        "android.hardware.neuralnetworks@1.3",
-        "libfmq",
-    ],
-    export_static_lib_headers: [
-        "neuralnetworks_utils_hal_common",
-    ],
 }
 
 cc_test {
     name: "neuralnetworks_utils_hal_1_3_test",
+    host_supported: true,
+    tidy_timeout_srcs: [
+        "test/DeviceTest.cpp",
+        "test/PreparedModelTest.cpp",
+    ],
     srcs: ["test/*.cpp"],
     static_libs: [
         "android.hardware.neuralnetworks@1.0",
@@ -58,7 +58,6 @@
         "android.hardware.neuralnetworks@1.2",
         "android.hardware.neuralnetworks@1.3",
         "libgmock",
-        "libneuralnetworks_common",
         "neuralnetworks_types",
         "neuralnetworks_utils_hal_common",
         "neuralnetworks_utils_hal_1_0",
@@ -67,16 +66,17 @@
         "neuralnetworks_utils_hal_1_3",
     ],
     shared_libs: [
-        "android.hidl.allocator@1.0",
-        "android.hidl.memory@1.0",
         "libbase",
         "libcutils",
         "libfmq",
         "libhidlbase",
-        "libhidlmemory",
         "liblog",
-        "libnativewindow",
         "libutils",
     ],
+    target: {
+        android: {
+            shared_libs: ["libnativewindow"],
+        },
+    },
     test_suites: ["general-tests"],
 }
diff --git a/neuralnetworks/1.3/utils/OWNERS b/neuralnetworks/1.3/utils/OWNERS
deleted file mode 100644
index e4feee3..0000000
--- a/neuralnetworks/1.3/utils/OWNERS
+++ /dev/null
@@ -1,11 +0,0 @@
-# Neuralnetworks team
-butlermichael@google.com
-dgross@google.com
-galarragas@google.com
-jeanluc@google.com
-levp@google.com
-miaowang@google.com
-pszczepaniak@google.com
-slavash@google.com
-vddang@google.com
-xusongw@google.com
diff --git a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Callbacks.h b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Callbacks.h
index 643172e..10892bc 100644
--- a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Callbacks.h
+++ b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Callbacks.h
@@ -30,8 +30,8 @@
 #include <nnapi/Result.h>
 #include <nnapi/Types.h>
 #include <nnapi/hal/1.0/Callbacks.h>
+#include <nnapi/hal/1.0/ProtectCallback.h>
 #include <nnapi/hal/CommonUtils.h>
-#include <nnapi/hal/ProtectCallback.h>
 #include <nnapi/hal/TransferValue.h>
 
 // See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
@@ -47,7 +47,8 @@
 
 // Converts the results of IDevice::prepareModel* to the NN canonical format. On success, this
 // function returns with a non-null nn::SharedPreparedModel with a feature level of
-// nn::Version::ANDROID_R. On failure, this function returns with the appropriate nn::GeneralError.
+// nn::kVersionFeatureLevel4. On failure, this function returns with the appropriate
+// nn::GeneralError.
 nn::GeneralResult<nn::SharedPreparedModel> prepareModelCallback(
         ErrorStatus status, const sp<IPreparedModel>& preparedModel);
 
diff --git a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Conversions.h b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Conversions.h
index b677c62..ec1e530 100644
--- a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Conversions.h
+++ b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Conversions.h
@@ -113,6 +113,9 @@
 nn::GeneralResult<V1_2::MeasureTiming> convert(const nn::MeasureTiming& measureTiming);
 nn::GeneralResult<V1_2::Timing> convert(const nn::Timing& timing);
 
+nn::GeneralResult<hidl_vec<hidl_handle>> convertSyncFences(
+        const std::vector<nn::SyncFence>& fences);
+
 }  // namespace android::hardware::neuralnetworks::V1_3::utils
 
 #endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_3_CONVERSIONS_H
diff --git a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Device.h b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Device.h
index 84f606a..cf5e5ea0 100644
--- a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Device.h
+++ b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Device.h
@@ -23,8 +23,8 @@
 #include <nnapi/OperandTypes.h>
 #include <nnapi/Result.h>
 #include <nnapi/Types.h>
+#include <nnapi/hal/1.0/ProtectCallback.h>
 #include <nnapi/hal/CommonUtils.h>
-#include <nnapi/hal/ProtectCallback.h>
 
 #include <functional>
 #include <memory>
@@ -66,8 +66,9 @@
     nn::GeneralResult<nn::SharedPreparedModel> prepareModel(
             const nn::Model& model, nn::ExecutionPreference preference, nn::Priority priority,
             nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
-            const std::vector<nn::SharedHandle>& dataCache,
-            const nn::CacheToken& token) const override;
+            const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
 
     nn::GeneralResult<nn::SharedPreparedModel> prepareModelFromCache(
             nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
diff --git a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/PreparedModel.h b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/PreparedModel.h
index 5acba71..124cc43 100644
--- a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/PreparedModel.h
+++ b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/PreparedModel.h
@@ -21,8 +21,8 @@
 #include <nnapi/IPreparedModel.h>
 #include <nnapi/Result.h>
 #include <nnapi/Types.h>
+#include <nnapi/hal/1.0/ProtectCallback.h>
 #include <nnapi/hal/CommonUtils.h>
-#include <nnapi/hal/ProtectCallback.h>
 
 #include <memory>
 #include <tuple>
@@ -48,18 +48,23 @@
 
     nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
             const nn::Request& request, nn::MeasureTiming measure,
-            const nn::OptionalTimePoint& deadline,
-            const nn::OptionalDuration& loopTimeoutDuration) const override;
+            const nn::OptionalTimePoint& deadline, const nn::OptionalDuration& loopTimeoutDuration,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
 
     nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>> executeFenced(
             const nn::Request& request, const std::vector<nn::SyncFence>& waitFor,
             nn::MeasureTiming measure, const nn::OptionalTimePoint& deadline,
             const nn::OptionalDuration& loopTimeoutDuration,
-            const nn::OptionalDuration& timeoutDurationAfterFence) const override;
+            const nn::OptionalDuration& timeoutDurationAfterFence,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
 
     nn::GeneralResult<nn::SharedExecution> createReusableExecution(
             const nn::Request& request, nn::MeasureTiming measure,
-            const nn::OptionalDuration& loopTimeoutDuration) const override;
+            const nn::OptionalDuration& loopTimeoutDuration,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
 
     nn::GeneralResult<nn::SharedBurst> configureExecutionBurst() const override;
 
diff --git a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Utils.h b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Utils.h
index 1d76caa..594d727 100644
--- a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Utils.h
+++ b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Utils.h
@@ -30,7 +30,6 @@
 #include <nnapi/hal/1.1/Utils.h>
 #include <nnapi/hal/1.2/Conversions.h>
 #include <nnapi/hal/1.2/Utils.h>
-#include <nnapi/hal/HandleError.h>
 
 namespace android::hardware::neuralnetworks::V1_3::utils {
 
@@ -40,7 +39,7 @@
 using V1_2::utils::kNoTiming;
 
 constexpr auto kDefaultPriority = Priority::MEDIUM;
-constexpr auto kVersion = nn::Version::ANDROID_R;
+constexpr auto kVersion = nn::kVersionFeatureLevel4;
 
 template <typename Type>
 nn::Result<void> validate(const Type& halObject) {
@@ -61,9 +60,9 @@
 }
 
 template <typename Type>
-nn::GeneralResult<void> compliantVersion(const Type& canonical) {
-    const auto version = NN_TRY(hal::utils::makeGeneralFailure(nn::validate(canonical)));
-    if (version > kVersion) {
+nn::Result<void> compliantVersion(const Type& canonical) {
+    const auto version = NN_TRY(nn::validate(canonical));
+    if (!nn::isCompliantVersion(version, kVersion)) {
         return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion;
     }
     return {};
diff --git a/neuralnetworks/1.3/utils/src/Buffer.cpp b/neuralnetworks/1.3/utils/src/Buffer.cpp
index ada5265..34925ea 100644
--- a/neuralnetworks/1.3/utils/src/Buffer.cpp
+++ b/neuralnetworks/1.3/utils/src/Buffer.cpp
@@ -25,7 +25,7 @@
 #include <nnapi/Result.h>
 #include <nnapi/Types.h>
 #include <nnapi/hal/1.0/Conversions.h>
-#include <nnapi/hal/HandleError.h>
+#include <nnapi/hal/1.0/HandleError.h>
 
 #include "Conversions.h"
 #include "Utils.h"
@@ -66,7 +66,7 @@
 
     const auto ret = kBuffer->copyTo(hidlDst);
     const auto status = HANDLE_TRANSPORT_FAILURE(ret);
-    HANDLE_HAL_STATUS(status) << "IBuffer::copyTo failed with " << toString(status);
+    HANDLE_STATUS_HIDL(status) << "IBuffer::copyTo failed with " << toString(status);
 
     return {};
 }
@@ -78,7 +78,7 @@
 
     const auto ret = kBuffer->copyFrom(hidlSrc, hidlDimensions);
     const auto status = HANDLE_TRANSPORT_FAILURE(ret);
-    HANDLE_HAL_STATUS(status) << "IBuffer::copyFrom failed with " << toString(status);
+    HANDLE_STATUS_HIDL(status) << "IBuffer::copyFrom failed with " << toString(status);
 
     return {};
 }
diff --git a/neuralnetworks/1.3/utils/src/Callbacks.cpp b/neuralnetworks/1.3/utils/src/Callbacks.cpp
index 8e9fb83..f063862 100644
--- a/neuralnetworks/1.3/utils/src/Callbacks.cpp
+++ b/neuralnetworks/1.3/utils/src/Callbacks.cpp
@@ -30,13 +30,13 @@
 #include <nnapi/Types.h>
 #include <nnapi/hal/1.0/Callbacks.h>
 #include <nnapi/hal/1.0/Conversions.h>
+#include <nnapi/hal/1.0/HandleError.h>
 #include <nnapi/hal/1.0/PreparedModel.h>
+#include <nnapi/hal/1.0/ProtectCallback.h>
 #include <nnapi/hal/1.2/Callbacks.h>
 #include <nnapi/hal/1.2/Conversions.h>
 #include <nnapi/hal/1.2/PreparedModel.h>
 #include <nnapi/hal/CommonUtils.h>
-#include <nnapi/hal/HandleError.h>
-#include <nnapi/hal/ProtectCallback.h>
 #include <nnapi/hal/TransferValue.h>
 
 #include <utility>
@@ -71,13 +71,13 @@
 
 nn::GeneralResult<std::vector<bool>> supportedOperationsCallback(
         ErrorStatus status, const hidl_vec<bool>& supportedOperations) {
-    HANDLE_HAL_STATUS(status) << "get supported operations failed with " << toString(status);
+    HANDLE_STATUS_HIDL(status) << "get supported operations failed with " << toString(status);
     return supportedOperations;
 }
 
 nn::GeneralResult<nn::SharedPreparedModel> prepareModelCallback(
         ErrorStatus status, const sp<IPreparedModel>& preparedModel) {
-    HANDLE_HAL_STATUS(status) << "model preparation failed with " << toString(status);
+    HANDLE_STATUS_HIDL(status) << "model preparation failed with " << toString(status);
     return NN_TRY(PreparedModel::create(preparedModel, /*executeSynchronously=*/true));
 }
 
@@ -90,9 +90,8 @@
         return NN_ERROR(nn::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE, std::move(canonicalOutputShapes))
                << "execution failed with " << toString(status);
     }
-    HANDLE_HAL_STATUS(status) << "execution failed with " << toString(status);
-    return hal::utils::makeExecutionFailure(
-            convertExecutionGeneralResultsHelper(outputShapes, timing));
+    HANDLE_STATUS_HIDL(status) << "execution failed with " << toString(status);
+    return convertExecutionGeneralResultsHelper(outputShapes, timing);
 }
 
 Return<void> PreparedModelCallback::notify(V1_0::ErrorStatus status,
diff --git a/neuralnetworks/1.3/utils/src/Conversions.cpp b/neuralnetworks/1.3/utils/src/Conversions.cpp
index e8a4f55..4eeb414 100644
--- a/neuralnetworks/1.3/utils/src/Conversions.cpp
+++ b/neuralnetworks/1.3/utils/src/Conversions.cpp
@@ -28,7 +28,6 @@
 #include <nnapi/hal/1.0/Conversions.h>
 #include <nnapi/hal/1.2/Conversions.h>
 #include <nnapi/hal/CommonUtils.h>
-#include <nnapi/hal/HandleError.h>
 
 #include <algorithm>
 #include <chrono>
@@ -131,32 +130,38 @@
     }
 
     auto operandPerformance = NN_TRY(unvalidatedConvert(capabilities.operandPerformance));
-    auto table = NN_TRY(hal::utils::makeGeneralFailure(
-            Capabilities::OperandPerformanceTable::create(std::move(operandPerformance)),
-            nn::ErrorStatus::GENERAL_FAILURE));
+    auto table =
+            NN_TRY(Capabilities::OperandPerformanceTable::create(std::move(operandPerformance)));
 
+    const auto relaxedFloat32toFloat16PerformanceScalar =
+            NN_TRY(unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceScalar));
+    const auto relaxedFloat32toFloat16PerformanceTensor =
+            NN_TRY(unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor));
+    const auto ifPerformance = NN_TRY(unvalidatedConvert(capabilities.ifPerformance));
+    const auto whilePerformance = NN_TRY(unvalidatedConvert(capabilities.whilePerformance));
     return Capabilities{
-            .relaxedFloat32toFloat16PerformanceScalar = NN_TRY(
-                    unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceScalar)),
-            .relaxedFloat32toFloat16PerformanceTensor = NN_TRY(
-                    unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor)),
+            .relaxedFloat32toFloat16PerformanceScalar = relaxedFloat32toFloat16PerformanceScalar,
+            .relaxedFloat32toFloat16PerformanceTensor = relaxedFloat32toFloat16PerformanceTensor,
             .operandPerformance = std::move(table),
-            .ifPerformance = NN_TRY(unvalidatedConvert(capabilities.ifPerformance)),
-            .whilePerformance = NN_TRY(unvalidatedConvert(capabilities.whilePerformance)),
+            .ifPerformance = ifPerformance,
+            .whilePerformance = whilePerformance,
     };
 }
 
 GeneralResult<Capabilities::OperandPerformance> unvalidatedConvert(
         const hal::V1_3::Capabilities::OperandPerformance& operandPerformance) {
+    const auto type = NN_TRY(unvalidatedConvert(operandPerformance.type));
+    const auto info = NN_TRY(unvalidatedConvert(operandPerformance.info));
     return Capabilities::OperandPerformance{
-            .type = NN_TRY(unvalidatedConvert(operandPerformance.type)),
-            .info = NN_TRY(unvalidatedConvert(operandPerformance.info)),
+            .type = type,
+            .info = info,
     };
 }
 
 GeneralResult<Operation> unvalidatedConvert(const hal::V1_3::Operation& operation) {
+    const auto type = NN_TRY(unvalidatedConvert(operation.type));
     return Operation{
-            .type = NN_TRY(unvalidatedConvert(operation.type)),
+            .type = type,
             .inputs = operation.inputs,
             .outputs = operation.outputs,
     };
@@ -168,25 +173,34 @@
 }
 
 GeneralResult<Operand> unvalidatedConvert(const hal::V1_3::Operand& operand) {
+    const auto type = NN_TRY(unvalidatedConvert(operand.type));
+    const auto lifetime = NN_TRY(unvalidatedConvert(operand.lifetime));
+    const auto location = NN_TRY(unvalidatedConvert(operand.location));
+    auto extraParams = NN_TRY(unvalidatedConvert(operand.extraParams));
     return Operand{
-            .type = NN_TRY(unvalidatedConvert(operand.type)),
+            .type = type,
             .dimensions = operand.dimensions,
             .scale = operand.scale,
             .zeroPoint = operand.zeroPoint,
-            .lifetime = NN_TRY(unvalidatedConvert(operand.lifetime)),
-            .location = NN_TRY(unvalidatedConvert(operand.location)),
-            .extraParams = NN_TRY(unvalidatedConvert(operand.extraParams)),
+            .lifetime = lifetime,
+            .location = location,
+            .extraParams = std::move(extraParams),
     };
 }
 
 GeneralResult<Model> unvalidatedConvert(const hal::V1_3::Model& model) {
+    auto main = NN_TRY(unvalidatedConvert(model.main));
+    auto referenced = NN_TRY(unvalidatedConvert(model.referenced));
+    auto operandValues = NN_TRY(unvalidatedConvert(model.operandValues));
+    auto pools = NN_TRY(unvalidatedConvert(model.pools));
+    auto extensionNameToPrefix = NN_TRY(unvalidatedConvert(model.extensionNameToPrefix));
     return Model{
-            .main = NN_TRY(unvalidatedConvert(model.main)),
-            .referenced = NN_TRY(unvalidatedConvert(model.referenced)),
-            .operandValues = NN_TRY(unvalidatedConvert(model.operandValues)),
-            .pools = NN_TRY(unvalidatedConvert(model.pools)),
+            .main = std::move(main),
+            .referenced = std::move(referenced),
+            .operandValues = std::move(operandValues),
+            .pools = std::move(pools),
             .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
-            .extensionNameToPrefix = NN_TRY(unvalidatedConvert(model.extensionNameToPrefix)),
+            .extensionNameToPrefix = std::move(extensionNameToPrefix),
     };
 }
 
@@ -195,7 +209,7 @@
 
     // Verify number of consumers.
     const auto numberOfConsumers =
-            NN_TRY(hal::utils::countNumberOfConsumers(subgraph.operands.size(), operations));
+            NN_TRY(countNumberOfConsumers(subgraph.operands.size(), operations));
     CHECK(subgraph.operands.size() == numberOfConsumers.size());
     for (size_t i = 0; i < subgraph.operands.size(); ++i) {
         if (subgraph.operands[i].numberOfConsumers != numberOfConsumers[i]) {
@@ -206,8 +220,9 @@
         }
     }
 
+    auto operands = NN_TRY(unvalidatedConvert(subgraph.operands));
     return Model::Subgraph{
-            .operands = NN_TRY(unvalidatedConvert(subgraph.operands)),
+            .operands = std::move(operands),
             .operations = std::move(operations),
             .inputIndexes = subgraph.inputIndexes,
             .outputIndexes = subgraph.outputIndexes,
@@ -227,10 +242,13 @@
 }
 
 GeneralResult<Request> unvalidatedConvert(const hal::V1_3::Request& request) {
+    auto inputs = NN_TRY(unvalidatedConvert(request.inputs));
+    auto outputs = NN_TRY(unvalidatedConvert(request.outputs));
+    auto pools = NN_TRY(unvalidatedConvert(request.pools));
     return Request{
-            .inputs = NN_TRY(unvalidatedConvert(request.inputs)),
-            .outputs = NN_TRY(unvalidatedConvert(request.outputs)),
-            .pools = NN_TRY(unvalidatedConvert(request.pools)),
+            .inputs = std::move(inputs),
+            .outputs = std::move(outputs),
+            .pools = std::move(pools),
     };
 }
 
@@ -239,7 +257,7 @@
     using Discriminator = hal::V1_3::Request::MemoryPool::hidl_discriminator;
     switch (memoryPool.getDiscriminator()) {
         case Discriminator::hidlMemory:
-            return hal::utils::createSharedMemoryFromHidlMemory(memoryPool.hidlMemory());
+            return unvalidatedConvert(memoryPool.hidlMemory());
         case Discriminator::token:
             return static_cast<Request::MemoryDomainToken>(memoryPool.token());
     }
@@ -381,7 +399,7 @@
 }
 
 nn::GeneralResult<hidl_handle> unvalidatedConvert(const nn::SharedHandle& handle) {
-    return V1_2::utils::unvalidatedConvert(handle);
+    return V1_0::utils::unvalidatedConvert(handle);
 }
 
 nn::GeneralResult<hidl_memory> unvalidatedConvert(const nn::SharedMemory& memory) {
@@ -398,7 +416,7 @@
 }
 
 nn::GeneralResult<V1_2::Model::ExtensionNameAndPrefix> unvalidatedConvert(
-        const nn::Model::ExtensionNameAndPrefix& extensionNameAndPrefix) {
+        const nn::ExtensionNameAndPrefix& extensionNameAndPrefix) {
     return V1_2::utils::unvalidatedConvert(extensionNameAndPrefix);
 }
 
@@ -465,37 +483,45 @@
 }
 
 nn::GeneralResult<Capabilities> unvalidatedConvert(const nn::Capabilities& capabilities) {
-    std::vector<nn::Capabilities::OperandPerformance> operandPerformance;
-    operandPerformance.reserve(capabilities.operandPerformance.asVector().size());
+    std::vector<nn::Capabilities::OperandPerformance> filteredOperandPerformances;
+    filteredOperandPerformances.reserve(capabilities.operandPerformance.asVector().size());
     std::copy_if(capabilities.operandPerformance.asVector().begin(),
                  capabilities.operandPerformance.asVector().end(),
-                 std::back_inserter(operandPerformance),
+                 std::back_inserter(filteredOperandPerformances),
                  [](const nn::Capabilities::OperandPerformance& operandPerformance) {
                      return compliantVersion(operandPerformance.type).has_value();
                  });
 
+    const auto relaxedFloat32toFloat16PerformanceScalar =
+            NN_TRY(unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceScalar));
+    const auto relaxedFloat32toFloat16PerformanceTensor =
+            NN_TRY(unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor));
+    auto operandPerformance = NN_TRY(unvalidatedConvert(filteredOperandPerformances));
+    const auto ifPerformance = NN_TRY(unvalidatedConvert(capabilities.ifPerformance));
+    const auto whilePerformance = NN_TRY(unvalidatedConvert(capabilities.whilePerformance));
     return Capabilities{
-            .relaxedFloat32toFloat16PerformanceScalar = NN_TRY(
-                    unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceScalar)),
-            .relaxedFloat32toFloat16PerformanceTensor = NN_TRY(
-                    unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor)),
-            .operandPerformance = NN_TRY(unvalidatedConvert(operandPerformance)),
-            .ifPerformance = NN_TRY(unvalidatedConvert(capabilities.ifPerformance)),
-            .whilePerformance = NN_TRY(unvalidatedConvert(capabilities.whilePerformance)),
+            .relaxedFloat32toFloat16PerformanceScalar = relaxedFloat32toFloat16PerformanceScalar,
+            .relaxedFloat32toFloat16PerformanceTensor = relaxedFloat32toFloat16PerformanceTensor,
+            .operandPerformance = std::move(operandPerformance),
+            .ifPerformance = ifPerformance,
+            .whilePerformance = whilePerformance,
     };
 }
 
 nn::GeneralResult<Capabilities::OperandPerformance> unvalidatedConvert(
         const nn::Capabilities::OperandPerformance& operandPerformance) {
+    const auto type = NN_TRY(unvalidatedConvert(operandPerformance.type));
+    const auto info = NN_TRY(unvalidatedConvert(operandPerformance.info));
     return Capabilities::OperandPerformance{
-            .type = NN_TRY(unvalidatedConvert(operandPerformance.type)),
-            .info = NN_TRY(unvalidatedConvert(operandPerformance.info)),
+            .type = type,
+            .info = info,
     };
 }
 
 nn::GeneralResult<Operation> unvalidatedConvert(const nn::Operation& operation) {
+    const auto type = NN_TRY(unvalidatedConvert(operation.type));
     return Operation{
-            .type = NN_TRY(unvalidatedConvert(operation.type)),
+            .type = type,
             .inputs = operation.inputs,
             .outputs = operation.outputs,
     };
@@ -511,15 +537,19 @@
 }
 
 nn::GeneralResult<Operand> unvalidatedConvert(const nn::Operand& operand) {
+    const auto type = NN_TRY(unvalidatedConvert(operand.type));
+    const auto lifetime = NN_TRY(unvalidatedConvert(operand.lifetime));
+    const auto location = NN_TRY(unvalidatedConvert(operand.location));
+    auto extraParams = NN_TRY(unvalidatedConvert(operand.extraParams));
     return Operand{
-            .type = NN_TRY(unvalidatedConvert(operand.type)),
+            .type = type,
             .dimensions = operand.dimensions,
             .numberOfConsumers = 0,
             .scale = operand.scale,
             .zeroPoint = operand.zeroPoint,
-            .lifetime = NN_TRY(unvalidatedConvert(operand.lifetime)),
-            .location = NN_TRY(unvalidatedConvert(operand.location)),
-            .extraParams = NN_TRY(unvalidatedConvert(operand.extraParams)),
+            .lifetime = lifetime,
+            .location = location,
+            .extraParams = std::move(extraParams),
     };
 }
 
@@ -529,13 +559,18 @@
                << "Model cannot be unvalidatedConverted because it contains pointer-based memory";
     }
 
+    auto main = NN_TRY(unvalidatedConvert(model.main));
+    auto referenced = NN_TRY(unvalidatedConvert(model.referenced));
+    auto operandValues = NN_TRY(unvalidatedConvert(model.operandValues));
+    auto pools = NN_TRY(unvalidatedConvert(model.pools));
+    auto extensionNameToPrefix = NN_TRY(unvalidatedConvert(model.extensionNameToPrefix));
     return Model{
-            .main = NN_TRY(unvalidatedConvert(model.main)),
-            .referenced = NN_TRY(unvalidatedConvert(model.referenced)),
-            .operandValues = NN_TRY(unvalidatedConvert(model.operandValues)),
-            .pools = NN_TRY(unvalidatedConvert(model.pools)),
+            .main = std::move(main),
+            .referenced = std::move(referenced),
+            .operandValues = std::move(operandValues),
+            .pools = std::move(pools),
             .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
-            .extensionNameToPrefix = NN_TRY(unvalidatedConvert(model.extensionNameToPrefix)),
+            .extensionNameToPrefix = std::move(extensionNameToPrefix),
     };
 }
 
@@ -544,15 +579,16 @@
 
     // Update number of consumers.
     const auto numberOfConsumers =
-            NN_TRY(hal::utils::countNumberOfConsumers(operands.size(), subgraph.operations));
+            NN_TRY(countNumberOfConsumers(operands.size(), subgraph.operations));
     CHECK(operands.size() == numberOfConsumers.size());
     for (size_t i = 0; i < operands.size(); ++i) {
         operands[i].numberOfConsumers = numberOfConsumers[i];
     }
 
+    auto operations = NN_TRY(unvalidatedConvert(subgraph.operations));
     return Subgraph{
             .operands = std::move(operands),
-            .operations = NN_TRY(unvalidatedConvert(subgraph.operations)),
+            .operations = std::move(operations),
             .inputIndexes = subgraph.inputIndexes,
             .outputIndexes = subgraph.outputIndexes,
     };
@@ -576,10 +612,13 @@
                << "Request cannot be unvalidatedConverted because it contains pointer-based memory";
     }
 
+    auto inputs = NN_TRY(unvalidatedConvert(request.inputs));
+    auto outputs = NN_TRY(unvalidatedConvert(request.outputs));
+    auto pools = NN_TRY(unvalidatedConvert(request.pools));
     return Request{
-            .inputs = NN_TRY(unvalidatedConvert(request.inputs)),
-            .outputs = NN_TRY(unvalidatedConvert(request.outputs)),
-            .pools = NN_TRY(unvalidatedConvert(request.pools)),
+            .inputs = std::move(inputs),
+            .outputs = std::move(outputs),
+            .pools = std::move(pools),
     };
 }
 
@@ -728,4 +767,13 @@
     return V1_2::utils::convert(timing);
 }
 
+nn::GeneralResult<hidl_vec<hidl_handle>> convertSyncFences(
+        const std::vector<nn::SyncFence>& syncFences) {
+    std::vector<nn::SharedHandle> handles;
+    handles.reserve(syncFences.size());
+    std::transform(syncFences.begin(), syncFences.end(), std::back_inserter(handles),
+                   [](const nn::SyncFence& syncFence) { return syncFence.getSharedHandle(); });
+    return convert(handles);
+}
+
 }  // namespace android::hardware::neuralnetworks::V1_3::utils
diff --git a/neuralnetworks/1.3/utils/src/Device.cpp b/neuralnetworks/1.3/utils/src/Device.cpp
index d710b85..824cec6 100644
--- a/neuralnetworks/1.3/utils/src/Device.cpp
+++ b/neuralnetworks/1.3/utils/src/Device.cpp
@@ -33,13 +33,13 @@
 #include <nnapi/OperandTypes.h>
 #include <nnapi/Result.h>
 #include <nnapi/Types.h>
+#include <nnapi/hal/1.0/HandleError.h>
+#include <nnapi/hal/1.0/ProtectCallback.h>
 #include <nnapi/hal/1.1/Conversions.h>
 #include <nnapi/hal/1.2/Conversions.h>
 #include <nnapi/hal/1.2/Device.h>
 #include <nnapi/hal/1.2/Utils.h>
 #include <nnapi/hal/CommonUtils.h>
-#include <nnapi/hal/HandleError.h>
-#include <nnapi/hal/ProtectCallback.h>
 
 #include <any>
 #include <functional>
@@ -72,7 +72,7 @@
 
 nn::GeneralResult<nn::Capabilities> capabilitiesCallback(ErrorStatus status,
                                                          const Capabilities& capabilities) {
-    HANDLE_HAL_STATUS(status) << "getting capabilities failed with " << toString(status);
+    HANDLE_STATUS_HIDL(status) << "getting capabilities failed with " << toString(status);
     return nn::convert(capabilities);
 }
 
@@ -89,7 +89,7 @@
 
 nn::GeneralResult<nn::SharedBuffer> allocationCallback(ErrorStatus status,
                                                        const sp<IBuffer>& buffer, uint32_t token) {
-    HANDLE_HAL_STATUS(status) << "IDevice::allocate failed with " << toString(status);
+    HANDLE_STATUS_HIDL(status) << "IDevice::allocate failed with " << toString(status);
     return Buffer::create(buffer, static_cast<nn::Request::MemoryDomainToken>(token));
 }
 
@@ -143,7 +143,7 @@
 }
 
 nn::Version Device::getFeatureLevel() const {
-    return nn::Version::ANDROID_R;
+    return kVersion;
 }
 
 nn::DeviceType Device::getType() const {
@@ -187,7 +187,9 @@
 nn::GeneralResult<nn::SharedPreparedModel> Device::prepareModel(
         const nn::Model& model, nn::ExecutionPreference preference, nn::Priority priority,
         nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
-        const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token) const {
+        const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token,
+        const std::vector<nn::TokenValuePair>& /*hints*/,
+        const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
     // Ensure that model is ready for IPC.
     std::optional<nn::Model> maybeModelInShared;
     const nn::Model& modelInShared =
@@ -208,7 +210,7 @@
             kDevice->prepareModel_1_3(hidlModel, hidlPreference, hidlPriority, hidlDeadline,
                                       hidlModelCache, hidlDataCache, hidlToken, cb);
     const auto status = HANDLE_TRANSPORT_FAILURE(ret);
-    HANDLE_HAL_STATUS(status) << "model preparation failed with " << toString(status);
+    HANDLE_STATUS_HIDL(status) << "model preparation failed with " << toString(status);
 
     return cb->get();
 }
@@ -227,7 +229,7 @@
     const auto ret = kDevice->prepareModelFromCache_1_3(hidlDeadline, hidlModelCache, hidlDataCache,
                                                         hidlToken, cb);
     const auto status = HANDLE_TRANSPORT_FAILURE(ret);
-    HANDLE_HAL_STATUS(status) << "model preparation from cache failed with " << toString(status);
+    HANDLE_STATUS_HIDL(status) << "model preparation from cache failed with " << toString(status);
 
     return cb->get();
 }
diff --git a/neuralnetworks/1.3/utils/src/Execution.cpp b/neuralnetworks/1.3/utils/src/Execution.cpp
index 3d17cc3..0ec7f56 100644
--- a/neuralnetworks/1.3/utils/src/Execution.cpp
+++ b/neuralnetworks/1.3/utils/src/Execution.cpp
@@ -29,7 +29,6 @@
 #include <nnapi/Result.h>
 #include <nnapi/Types.h>
 #include <nnapi/hal/CommonUtils.h>
-#include <nnapi/hal/HandleError.h>
 
 #include <memory>
 #include <utility>
@@ -65,7 +64,7 @@
 
 nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> Execution::compute(
         const nn::OptionalTimePoint& deadline) const {
-    const auto hidlDeadline = NN_TRY(hal::utils::makeExecutionFailure(convert(deadline)));
+    const auto hidlDeadline = NN_TRY(convert(deadline));
     return kPreparedModel->executeInternal(kRequest, kMeasure, hidlDeadline, kLoopTimeoutDuration,
                                            kRelocation);
 }
@@ -73,7 +72,7 @@
 nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>> Execution::computeFenced(
         const std::vector<nn::SyncFence>& waitFor, const nn::OptionalTimePoint& deadline,
         const nn::OptionalDuration& timeoutDurationAfterFence) const {
-    const auto hidlWaitFor = NN_TRY(hal::utils::convertSyncFences(waitFor));
+    const auto hidlWaitFor = NN_TRY(convertSyncFences(waitFor));
     const auto hidlDeadline = NN_TRY(convert(deadline));
     const auto hidlTimeoutDurationAfterFence = NN_TRY(convert(timeoutDurationAfterFence));
     return kPreparedModel->executeFencedInternal(kRequest, hidlWaitFor, kMeasure, hidlDeadline,
diff --git a/neuralnetworks/1.3/utils/src/PreparedModel.cpp b/neuralnetworks/1.3/utils/src/PreparedModel.cpp
index 1623de5..b92f877 100644
--- a/neuralnetworks/1.3/utils/src/PreparedModel.cpp
+++ b/neuralnetworks/1.3/utils/src/PreparedModel.cpp
@@ -30,12 +30,12 @@
 #include <nnapi/Result.h>
 #include <nnapi/TypeUtils.h>
 #include <nnapi/Types.h>
+#include <nnapi/hal/1.0/HandleError.h>
+#include <nnapi/hal/1.0/ProtectCallback.h>
+#include <nnapi/hal/1.2/Burst.h>
+#include <nnapi/hal/1.2/BurstUtils.h>
 #include <nnapi/hal/1.2/Conversions.h>
-#include <nnapi/hal/1.2/ExecutionBurstController.h>
-#include <nnapi/hal/1.2/ExecutionBurstUtils.h>
 #include <nnapi/hal/CommonUtils.h>
-#include <nnapi/hal/HandleError.h>
-#include <nnapi/hal/ProtectCallback.h>
 
 #include <memory>
 #include <tuple>
@@ -50,20 +50,19 @@
 
 nn::GeneralResult<std::pair<nn::Timing, nn::Timing>> convertFencedExecutionCallbackResults(
         ErrorStatus status, const V1_2::Timing& timingLaunched, const V1_2::Timing& timingFenced) {
-    HANDLE_HAL_STATUS(status) << "fenced execution callback info failed with " << toString(status);
+    HANDLE_STATUS_HIDL(status) << "fenced execution callback info failed with " << toString(status);
     return std::make_pair(NN_TRY(nn::convert(timingLaunched)), NN_TRY(nn::convert(timingFenced)));
 }
 
 nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>> fencedExecutionCallback(
         ErrorStatus status, const hidl_handle& syncFence,
         const sp<IFencedExecutionCallback>& callback) {
-    HANDLE_HAL_STATUS(status) << "fenced execution failed with " << toString(status);
+    HANDLE_STATUS_HIDL(status) << "fenced execution failed with " << toString(status);
 
     auto resultSyncFence = nn::SyncFence::createAsSignaled();
     if (syncFence.getNativeHandle() != nullptr) {
         auto sharedHandle = NN_TRY(nn::convert(syncFence));
-        resultSyncFence = NN_TRY(hal::utils::makeGeneralFailure(
-                nn::SyncFence::create(std::move(sharedHandle)), nn::ErrorStatus::GENERAL_FAILURE));
+        resultSyncFence = NN_TRY(nn::SyncFence::create(std::move(sharedHandle)));
     }
 
     if (callback == nullptr) {
@@ -128,7 +127,7 @@
             kPreparedModel->execute_1_3(request, measure, deadline, loopTimeoutDuration, cb);
     const auto status = HANDLE_TRANSPORT_FAILURE(ret);
     if (status != ErrorStatus::OUTPUT_INSUFFICIENT_SIZE) {
-        HANDLE_HAL_STATUS(status) << "execution failed with " << toString(status);
+        HANDLE_STATUS_HIDL(status) << "execution failed with " << toString(status);
     }
 
     return cb->get();
@@ -136,21 +135,20 @@
 
 nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> PreparedModel::execute(
         const nn::Request& request, nn::MeasureTiming measure,
-        const nn::OptionalTimePoint& deadline,
-        const nn::OptionalDuration& loopTimeoutDuration) const {
+        const nn::OptionalTimePoint& deadline, const nn::OptionalDuration& loopTimeoutDuration,
+        const std::vector<nn::TokenValuePair>& /*hints*/,
+        const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
     // Ensure that request is ready for IPC.
     std::optional<nn::Request> maybeRequestInShared;
     hal::utils::RequestRelocation relocation;
-    const nn::Request& requestInShared =
-            NN_TRY(hal::utils::makeExecutionFailure(hal::utils::convertRequestFromPointerToShared(
-                    &request, nn::kDefaultRequestMemoryAlignment, nn::kMinMemoryPadding,
-                    &maybeRequestInShared, &relocation)));
+    const nn::Request& requestInShared = NN_TRY(hal::utils::convertRequestFromPointerToShared(
+            &request, nn::kDefaultRequestMemoryAlignment, nn::kMinMemoryPadding,
+            &maybeRequestInShared, &relocation));
 
-    const auto hidlRequest = NN_TRY(hal::utils::makeExecutionFailure(convert(requestInShared)));
-    const auto hidlMeasure = NN_TRY(hal::utils::makeExecutionFailure(convert(measure)));
-    const auto hidlDeadline = NN_TRY(hal::utils::makeExecutionFailure(convert(deadline)));
-    const auto hidlLoopTimeoutDuration =
-            NN_TRY(hal::utils::makeExecutionFailure(convert(loopTimeoutDuration)));
+    const auto hidlRequest = NN_TRY(convert(requestInShared));
+    const auto hidlMeasure = NN_TRY(convert(measure));
+    const auto hidlDeadline = NN_TRY(convert(deadline));
+    const auto hidlLoopTimeoutDuration = NN_TRY(convert(loopTimeoutDuration));
 
     return executeInternal(hidlRequest, hidlMeasure, hidlDeadline, hidlLoopTimeoutDuration,
                            relocation);
@@ -177,10 +175,13 @@
 }
 
 nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>>
-PreparedModel::executeFenced(const nn::Request& request, const std::vector<nn::SyncFence>& waitFor,
-                             nn::MeasureTiming measure, const nn::OptionalTimePoint& deadline,
-                             const nn::OptionalDuration& loopTimeoutDuration,
-                             const nn::OptionalDuration& timeoutDurationAfterFence) const {
+PreparedModel::executeFenced(
+        const nn::Request& request, const std::vector<nn::SyncFence>& waitFor,
+        nn::MeasureTiming measure, const nn::OptionalTimePoint& deadline,
+        const nn::OptionalDuration& loopTimeoutDuration,
+        const nn::OptionalDuration& timeoutDurationAfterFence,
+        const std::vector<nn::TokenValuePair>& /*hints*/,
+        const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
     // Ensure that request is ready for IPC.
     std::optional<nn::Request> maybeRequestInShared;
     hal::utils::RequestRelocation relocation;
@@ -189,7 +190,7 @@
             &maybeRequestInShared, &relocation));
 
     const auto hidlRequest = NN_TRY(convert(requestInShared));
-    const auto hidlWaitFor = NN_TRY(hal::utils::convertSyncFences(waitFor));
+    const auto hidlWaitFor = NN_TRY(convertSyncFences(waitFor));
     const auto hidlMeasure = NN_TRY(convert(measure));
     const auto hidlDeadline = NN_TRY(convert(deadline));
     const auto hidlLoopTimeoutDuration = NN_TRY(convert(loopTimeoutDuration));
@@ -233,7 +234,9 @@
 
 nn::GeneralResult<nn::SharedExecution> PreparedModel::createReusableExecution(
         const nn::Request& request, nn::MeasureTiming measure,
-        const nn::OptionalDuration& loopTimeoutDuration) const {
+        const nn::OptionalDuration& loopTimeoutDuration,
+        const std::vector<nn::TokenValuePair>& /*hints*/,
+        const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
     // Ensure that request is ready for IPC.
     std::optional<nn::Request> maybeRequestInShared;
     hal::utils::RequestRelocation relocation;
@@ -249,17 +252,8 @@
 }
 
 nn::GeneralResult<nn::SharedBurst> PreparedModel::configureExecutionBurst() const {
-    auto self = shared_from_this();
-    auto fallback = [preparedModel = std::move(self)](
-                            const nn::Request& request, nn::MeasureTiming measure,
-                            const nn::OptionalTimePoint& deadline,
-                            const nn::OptionalDuration& loopTimeoutDuration)
-            -> nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> {
-        return preparedModel->execute(request, measure, deadline, loopTimeoutDuration);
-    };
     const auto pollingTimeWindow = V1_2::utils::getBurstControllerPollingTimeWindow();
-    return V1_2::utils::ExecutionBurstController::create(shared_from_this(), kPreparedModel,
-                                                         pollingTimeWindow);
+    return V1_2::utils::Burst::create(shared_from_this(), kPreparedModel, pollingTimeWindow);
 }
 
 std::any PreparedModel::getUnderlyingResource() const {
diff --git a/neuralnetworks/1.3/utils/test/DeviceTest.cpp b/neuralnetworks/1.3/utils/test/DeviceTest.cpp
index 2d1b2f2..6f48837 100644
--- a/neuralnetworks/1.3/utils/test/DeviceTest.cpp
+++ b/neuralnetworks/1.3/utils/test/DeviceTest.cpp
@@ -505,7 +505,7 @@
     const auto featureLevel = device->getFeatureLevel();
 
     // verify result
-    EXPECT_EQ(featureLevel, nn::Version::ANDROID_R);
+    EXPECT_EQ(featureLevel, nn::kVersionFeatureLevel4);
 }
 
 TEST(DeviceTest, getCachedData) {
@@ -658,7 +658,7 @@
 
     // run test
     const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
-                                             nn::Priority::DEFAULT, {}, {}, {}, {});
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_TRUE(result.has_value())
@@ -677,7 +677,7 @@
 
     // run test
     const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
-                                             nn::Priority::DEFAULT, {}, {}, {}, {});
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -695,7 +695,7 @@
 
     // run test
     const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
-                                             nn::Priority::DEFAULT, {}, {}, {}, {});
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -713,7 +713,7 @@
 
     // run test
     const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
-                                             nn::Priority::DEFAULT, {}, {}, {}, {});
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -730,7 +730,7 @@
 
     // run test
     const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
-                                             nn::Priority::DEFAULT, {}, {}, {}, {});
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -747,7 +747,7 @@
 
     // run test
     const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
-                                             nn::Priority::DEFAULT, {}, {}, {}, {});
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -768,7 +768,7 @@
 
     // run test
     const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
-                                             nn::Priority::DEFAULT, {}, {}, {}, {});
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
diff --git a/neuralnetworks/1.3/utils/test/PreparedModelTest.cpp b/neuralnetworks/1.3/utils/test/PreparedModelTest.cpp
index 6dbbd6b..51b5d29 100644
--- a/neuralnetworks/1.3/utils/test/PreparedModelTest.cpp
+++ b/neuralnetworks/1.3/utils/test/PreparedModelTest.cpp
@@ -182,7 +182,7 @@
             .WillOnce(Invoke(makeExecuteSynchronously(V1_3::ErrorStatus::NONE, {}, kNoTiming)));
 
     // run test
-    const auto result = preparedModel->execute({}, {}, {}, {});
+    const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
 
     // verify result
     EXPECT_TRUE(result.has_value())
@@ -200,7 +200,7 @@
                     makeExecuteSynchronously(V1_3::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming)));
 
     // run test
-    const auto result = preparedModel->execute({}, {}, {}, {});
+    const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -217,7 +217,7 @@
             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
 
     // run test
-    const auto result = preparedModel->execute({}, {}, {}, {});
+    const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -234,7 +234,7 @@
             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
 
     // run test
-    const auto result = preparedModel->execute({}, {}, {}, {});
+    const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -252,7 +252,7 @@
                                                        V1_3::ErrorStatus::NONE, {}, kNoTiming)));
 
     // run test
-    const auto result = preparedModel->execute({}, {}, {}, {});
+    const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
 
     // verify result
     EXPECT_TRUE(result.has_value())
@@ -271,7 +271,7 @@
                                                        kNoTiming)));
 
     // run test
-    const auto result = preparedModel->execute({}, {}, {}, {});
+    const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -289,7 +289,7 @@
                     V1_3::ErrorStatus::NONE, V1_3::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming)));
 
     // run test
-    const auto result = preparedModel->execute({}, {}, {}, {});
+    const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -306,7 +306,7 @@
             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
 
     // run test
-    const auto result = preparedModel->execute({}, {}, {}, {});
+    const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -323,7 +323,7 @@
             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
 
     // run test
-    const auto result = preparedModel->execute({}, {}, {}, {});
+    const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -344,7 +344,7 @@
             .WillOnce(InvokeWithoutArgs(ret));
 
     // run test
-    const auto result = preparedModel->execute({}, {}, {}, {});
+    const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -366,7 +366,7 @@
             .WillOnce(Invoke(makeExecuteFencedReturn(V1_3::ErrorStatus::NONE, {}, mockCallback)));
 
     // run test
-    const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
+    const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_TRUE(result.has_value())
@@ -396,7 +396,7 @@
             .WillOnce(Invoke(makeExecuteFencedReturn(V1_3::ErrorStatus::NONE, {}, mockCallback)));
 
     // run test
-    const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
+    const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_TRUE(result.has_value())
@@ -422,7 +422,7 @@
                     makeExecuteFencedReturn(V1_3::ErrorStatus::GENERAL_FAILURE, {}, nullptr)));
 
     // run test
-    const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
+    const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -439,7 +439,7 @@
             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
 
     // run test
-    const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
+    const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -456,7 +456,7 @@
             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
 
     // run test
-    const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
+    const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -475,7 +475,7 @@
                     Invoke(makeExecuteSynchronously(V1_3::ErrorStatus::NONE, {}, kNoTiming)));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -499,7 +499,7 @@
                     makeExecuteSynchronously(V1_3::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming)));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -520,7 +520,7 @@
             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -541,7 +541,7 @@
             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -564,7 +564,7 @@
                     V1_3::ErrorStatus::NONE, V1_3::ErrorStatus::NONE, {}, kNoTiming)));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -589,7 +589,7 @@
                                                        kNoTiming)));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -611,7 +611,7 @@
                     V1_3::ErrorStatus::NONE, V1_3::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming)));
 
     // run test
-    const auto result = preparedModel->execute({}, {}, {}, {});
+    const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -628,7 +628,7 @@
             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -649,7 +649,7 @@
             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -674,7 +674,7 @@
             .WillOnce(InvokeWithoutArgs(ret));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -702,7 +702,7 @@
                     Invoke(makeExecuteFencedReturn(V1_3::ErrorStatus::NONE, {}, mockCallback)));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -738,7 +738,7 @@
             .WillOnce(Invoke(makeExecuteFencedReturn(V1_3::ErrorStatus::NONE, {}, mockCallback)));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -768,7 +768,7 @@
                     makeExecuteFencedReturn(V1_3::ErrorStatus::GENERAL_FAILURE, {}, nullptr)));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -789,7 +789,7 @@
             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -810,7 +810,7 @@
             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
diff --git a/neuralnetworks/1.3/vts/OWNERS b/neuralnetworks/1.3/vts/OWNERS
deleted file mode 100644
index b5a8e1f..0000000
--- a/neuralnetworks/1.3/vts/OWNERS
+++ /dev/null
@@ -1,16 +0,0 @@
-# Neuralnetworks team
-butlermichael@google.com
-dgross@google.com
-jeanluc@google.com
-levp@google.com
-miaowang@google.com
-mikie@google.com
-mks@google.com
-pszczepaniak@google.com
-slavash@google.com
-vddang@google.com
-xusongw@google.com
-
-# VTS team
-yim@google.com
-yuexima@google.com
diff --git a/neuralnetworks/1.3/vts/functional/Android.bp b/neuralnetworks/1.3/vts/functional/Android.bp
index 7ae080f..9fa0f0a 100644
--- a/neuralnetworks/1.3/vts/functional/Android.bp
+++ b/neuralnetworks/1.3/vts/functional/Android.bp
@@ -45,6 +45,10 @@
 cc_test {
     name: "VtsHalNeuralnetworksV1_3TargetTest",
     defaults: ["neuralnetworks_vts_functional_defaults"],
+    tidy_timeout_srcs: [
+        "CompilationCachingTests.cpp",
+        "MemoryDomainTests.cpp",
+    ],
     srcs: [
         "BasicTests.cpp",
         "CompilationCachingTests.cpp",
@@ -66,7 +70,6 @@
         "VtsHalNeuralNetworksV1_0_utils",
         "VtsHalNeuralNetworksV1_2_utils",
         "VtsHalNeuralNetworksV1_3_utils",
-        "android.hardware.neuralnetworks-V2-ndk_platform",
         "android.hardware.neuralnetworks@1.0",
         "android.hardware.neuralnetworks@1.1",
         "android.hardware.neuralnetworks@1.2",
@@ -76,7 +79,7 @@
         "libgmock",
         "libhidlmemory",
         "libneuralnetworks_generated_test_harness",
-        "libneuralnetworks_utils",
+        "libneuralnetworks_common",
         "libsync",
     ],
     whole_static_libs: [
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/MemoryDomainTests.cpp b/neuralnetworks/1.3/vts/functional/MemoryDomainTests.cpp
index e2fa6e4..af3641a 100644
--- a/neuralnetworks/1.3/vts/functional/MemoryDomainTests.cpp
+++ b/neuralnetworks/1.3/vts/functional/MemoryDomainTests.cpp
@@ -1158,12 +1158,15 @@
     auto [buffer, token] = allocateBuffer(preparedModel, {0}, {0}, kTestOperand.dimensions);
     if (buffer == nullptr) return;
 
-    Request::MemoryPool sharedMemory = createSharedMemoryPool(kTestOperandDataSize);
-    Request::MemoryPool deviceMemory = createDeviceMemoryPool(token);
+    // Use an incompatible dimension and make sure the length matches with the bad dimension.
     auto badDimensions = kTestOperand.dimensions;
     badDimensions[0] = 2;
+    const uint32_t badTestOperandDataSize = kTestOperandDataSize * 2;
+
+    Request::MemoryPool sharedMemory = createSharedMemoryPool(badTestOperandDataSize);
+    Request::MemoryPool deviceMemory = createDeviceMemoryPool(token);
     RequestArgument sharedMemoryArg = {
-            .location = {.poolIndex = 0, .offset = 0, .length = kTestOperandDataSize},
+            .location = {.poolIndex = 0, .offset = 0, .length = badTestOperandDataSize},
             .dimensions = badDimensions};
     RequestArgument deviceMemoryArg = {.location = {.poolIndex = 1}};
     RequestArgument deviceMemoryArgWithBadDimensions = {.location = {.poolIndex = 1},
diff --git a/neuralnetworks/OWNERS b/neuralnetworks/OWNERS
new file mode 100644
index 0000000..04c5d72
--- /dev/null
+++ b/neuralnetworks/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 195575
+include platform/packages/modules/NeuralNetworks:/NNAPI_OWNERS  # Neuralnetworks team
diff --git a/neuralnetworks/README b/neuralnetworks/README
index d8c8f5d..b0c605d 100644
--- a/neuralnetworks/README
+++ b/neuralnetworks/README
@@ -1,2 +1,2 @@
 NeuralNetworks sample driver implementation is located at
-frameworks/ml/nn/driver/sample.
+packages/modules/NeuralNetworks/driver/sample*.
diff --git a/neuralnetworks/aidl/Android.bp b/neuralnetworks/aidl/Android.bp
index f5193df..aa4c4b6 100644
--- a/neuralnetworks/aidl/Android.bp
+++ b/neuralnetworks/aidl/Android.bp
@@ -9,14 +9,15 @@
 
 aidl_interface {
     name: "android.hardware.neuralnetworks",
+    host_supported: true,
     vendor_available: true,
     srcs: [
         "android/hardware/neuralnetworks/*.aidl",
     ],
     stability: "vintf",
     imports: [
-        "android.hardware.common",
-        "android.hardware.graphics.common",
+        "android.hardware.common-V2",
+        "android.hardware.graphics.common-V2",
     ],
     backend: {
         java: {
@@ -37,5 +38,6 @@
     versions: [
         "1",
         "2",
+        "3",
     ],
 }
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/.hash b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/.hash
new file mode 100644
index 0000000..3b9f018
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/.hash
@@ -0,0 +1 @@
+8c2c4ca2327e6f779dad6119c03d832ea4e1def1
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/BufferDesc.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/BufferDesc.aidl
new file mode 100644
index 0000000..05cec76
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/BufferDesc.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@VintfStability
+parcelable BufferDesc {
+  int[] dimensions;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/BufferRole.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/BufferRole.aidl
new file mode 100644
index 0000000..10a6b75
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/BufferRole.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@VintfStability
+parcelable BufferRole {
+  int modelIndex;
+  int ioIndex;
+  float probability;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Capabilities.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Capabilities.aidl
new file mode 100644
index 0000000..30877c0
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Capabilities.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@VintfStability
+parcelable Capabilities {
+  android.hardware.neuralnetworks.PerformanceInfo relaxedFloat32toFloat16PerformanceScalar;
+  android.hardware.neuralnetworks.PerformanceInfo relaxedFloat32toFloat16PerformanceTensor;
+  android.hardware.neuralnetworks.OperandPerformance[] operandPerformance;
+  android.hardware.neuralnetworks.PerformanceInfo ifPerformance;
+  android.hardware.neuralnetworks.PerformanceInfo whilePerformance;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/DataLocation.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/DataLocation.aidl
new file mode 100644
index 0000000..db49a38
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/DataLocation.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@VintfStability
+parcelable DataLocation {
+  int poolIndex;
+  long offset;
+  long length;
+  long padding;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/DeviceBuffer.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/DeviceBuffer.aidl
new file mode 100644
index 0000000..7cdd6db
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/DeviceBuffer.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@VintfStability
+parcelable DeviceBuffer {
+  android.hardware.neuralnetworks.IBuffer buffer;
+  int token;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/DeviceType.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/DeviceType.aidl
new file mode 100644
index 0000000..82fe8ae
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/DeviceType.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@Backing(type="int") @VintfStability
+enum DeviceType {
+  OTHER = 1,
+  CPU = 2,
+  GPU = 3,
+  ACCELERATOR = 4,
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/ErrorStatus.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/ErrorStatus.aidl
new file mode 100644
index 0000000..57d5d6e
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/ErrorStatus.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@Backing(type="int") @VintfStability
+enum ErrorStatus {
+  NONE = 0,
+  DEVICE_UNAVAILABLE = 1,
+  GENERAL_FAILURE = 2,
+  OUTPUT_INSUFFICIENT_SIZE = 3,
+  INVALID_ARGUMENT = 4,
+  MISSED_DEADLINE_TRANSIENT = 5,
+  MISSED_DEADLINE_PERSISTENT = 6,
+  RESOURCE_EXHAUSTED_TRANSIENT = 7,
+  RESOURCE_EXHAUSTED_PERSISTENT = 8,
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/ExecutionPreference.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/ExecutionPreference.aidl
new file mode 100644
index 0000000..4352d8f
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/ExecutionPreference.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@Backing(type="int") @VintfStability
+enum ExecutionPreference {
+  LOW_POWER = 0,
+  FAST_SINGLE_ANSWER = 1,
+  SUSTAINED_SPEED = 2,
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/ExecutionResult.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/ExecutionResult.aidl
new file mode 100644
index 0000000..44e9922
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/ExecutionResult.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+parcelable ExecutionResult {
+  boolean outputSufficientSize;
+  android.hardware.neuralnetworks.OutputShape[] outputShapes;
+  android.hardware.neuralnetworks.Timing timing;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Extension.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Extension.aidl
new file mode 100644
index 0000000..c47028d
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Extension.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@VintfStability
+parcelable Extension {
+  String name;
+  android.hardware.neuralnetworks.ExtensionOperandTypeInformation[] operandTypes;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/ExtensionNameAndPrefix.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/ExtensionNameAndPrefix.aidl
new file mode 100644
index 0000000..6c287fd
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/ExtensionNameAndPrefix.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@VintfStability
+parcelable ExtensionNameAndPrefix {
+  String name;
+  char prefix;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/ExtensionOperandTypeInformation.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/ExtensionOperandTypeInformation.aidl
new file mode 100644
index 0000000..a3680aa
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/ExtensionOperandTypeInformation.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@VintfStability
+parcelable ExtensionOperandTypeInformation {
+  char type;
+  boolean isTensor;
+  int byteSize;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/FencedExecutionResult.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/FencedExecutionResult.aidl
new file mode 100644
index 0000000..7952b34
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/FencedExecutionResult.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+parcelable FencedExecutionResult {
+  android.hardware.neuralnetworks.IFencedExecutionCallback callback;
+  @nullable ParcelFileDescriptor syncFence;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/FusedActivationFunc.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/FusedActivationFunc.aidl
new file mode 100644
index 0000000..7e61bbb
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/FusedActivationFunc.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@Backing(type="int") @VintfStability
+enum FusedActivationFunc {
+  NONE = 0,
+  RELU = 1,
+  RELU1 = 2,
+  RELU6 = 3,
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IBuffer.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IBuffer.aidl
new file mode 100644
index 0000000..f10e7e2
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IBuffer.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@VintfStability
+interface IBuffer {
+  void copyFrom(in android.hardware.neuralnetworks.Memory src, in int[] dimensions);
+  void copyTo(in android.hardware.neuralnetworks.Memory dst);
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IBurst.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IBurst.aidl
new file mode 100644
index 0000000..eb3d0b0
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IBurst.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+interface IBurst {
+  android.hardware.neuralnetworks.ExecutionResult executeSynchronously(in android.hardware.neuralnetworks.Request request, in long[] memoryIdentifierTokens, in boolean measureTiming, in long deadlineNs, in long loopTimeoutDurationNs);
+  void releaseMemoryResource(in long memoryIdentifierToken);
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IDevice.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IDevice.aidl
new file mode 100644
index 0000000..c9c67f2
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IDevice.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@VintfStability
+interface IDevice {
+  android.hardware.neuralnetworks.DeviceBuffer allocate(in android.hardware.neuralnetworks.BufferDesc desc, in android.hardware.neuralnetworks.IPreparedModelParcel[] preparedModels, in android.hardware.neuralnetworks.BufferRole[] inputRoles, in android.hardware.neuralnetworks.BufferRole[] outputRoles);
+  android.hardware.neuralnetworks.Capabilities getCapabilities();
+  android.hardware.neuralnetworks.NumberOfCacheFiles getNumberOfCacheFilesNeeded();
+  android.hardware.neuralnetworks.Extension[] getSupportedExtensions();
+  boolean[] getSupportedOperations(in android.hardware.neuralnetworks.Model model);
+  android.hardware.neuralnetworks.DeviceType getType();
+  String getVersionString();
+  void prepareModel(in android.hardware.neuralnetworks.Model model, in android.hardware.neuralnetworks.ExecutionPreference preference, in android.hardware.neuralnetworks.Priority priority, in long deadlineNs, in ParcelFileDescriptor[] modelCache, in ParcelFileDescriptor[] dataCache, in byte[] token, in android.hardware.neuralnetworks.IPreparedModelCallback callback);
+  void prepareModelFromCache(in long deadlineNs, in ParcelFileDescriptor[] modelCache, in ParcelFileDescriptor[] dataCache, in byte[] token, in android.hardware.neuralnetworks.IPreparedModelCallback callback);
+  const int BYTE_SIZE_OF_CACHE_TOKEN = 32;
+  const int MAX_NUMBER_OF_CACHE_FILES = 32;
+  const int EXTENSION_TYPE_HIGH_BITS_PREFIX = 15;
+  const int EXTENSION_TYPE_LOW_BITS_TYPE = 16;
+  const int OPERAND_TYPE_BASE_MAX = 65535;
+  const int OPERATION_TYPE_BASE_MAX = 65535;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IFencedExecutionCallback.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IFencedExecutionCallback.aidl
new file mode 100644
index 0000000..0bfb80a
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IFencedExecutionCallback.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@VintfStability
+interface IFencedExecutionCallback {
+  android.hardware.neuralnetworks.ErrorStatus getExecutionInfo(out android.hardware.neuralnetworks.Timing timingLaunched, out android.hardware.neuralnetworks.Timing timingFenced);
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IPreparedModel.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IPreparedModel.aidl
new file mode 100644
index 0000000..fccb5dc
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IPreparedModel.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@VintfStability
+interface IPreparedModel {
+  android.hardware.neuralnetworks.ExecutionResult executeSynchronously(in android.hardware.neuralnetworks.Request request, in boolean measureTiming, in long deadlineNs, in long loopTimeoutDurationNs);
+  android.hardware.neuralnetworks.FencedExecutionResult executeFenced(in android.hardware.neuralnetworks.Request request, in ParcelFileDescriptor[] waitFor, in boolean measureTiming, in long deadlineNs, in long loopTimeoutDurationNs, in long durationNs);
+  android.hardware.neuralnetworks.IBurst configureExecutionBurst();
+  const long DEFAULT_LOOP_TIMEOUT_DURATION_NS = 2000000000;
+  const long MAXIMUM_LOOP_TIMEOUT_DURATION_NS = 15000000000;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IPreparedModelCallback.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IPreparedModelCallback.aidl
new file mode 100644
index 0000000..e0c763b
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IPreparedModelCallback.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@VintfStability
+interface IPreparedModelCallback {
+  void notify(in android.hardware.neuralnetworks.ErrorStatus status, in android.hardware.neuralnetworks.IPreparedModel preparedModel);
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IPreparedModelParcel.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IPreparedModelParcel.aidl
new file mode 100644
index 0000000..dbedf12
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/IPreparedModelParcel.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@VintfStability
+parcelable IPreparedModelParcel {
+  android.hardware.neuralnetworks.IPreparedModel preparedModel;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Memory.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Memory.aidl
new file mode 100644
index 0000000..37fa102
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Memory.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@VintfStability
+union Memory {
+  android.hardware.common.Ashmem ashmem;
+  android.hardware.common.MappableFile mappableFile;
+  android.hardware.graphics.common.HardwareBuffer hardwareBuffer;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Model.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Model.aidl
new file mode 100644
index 0000000..30d8dda
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Model.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@VintfStability
+parcelable Model {
+  android.hardware.neuralnetworks.Subgraph main;
+  android.hardware.neuralnetworks.Subgraph[] referenced;
+  byte[] operandValues;
+  android.hardware.neuralnetworks.Memory[] pools;
+  boolean relaxComputationFloat32toFloat16;
+  android.hardware.neuralnetworks.ExtensionNameAndPrefix[] extensionNameToPrefix;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/NumberOfCacheFiles.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/NumberOfCacheFiles.aidl
new file mode 100644
index 0000000..9314760
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/NumberOfCacheFiles.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@VintfStability
+parcelable NumberOfCacheFiles {
+  int numModelCache;
+  int numDataCache;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Operand.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Operand.aidl
new file mode 100644
index 0000000..1d9bdd8
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Operand.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@VintfStability
+parcelable Operand {
+  android.hardware.neuralnetworks.OperandType type = android.hardware.neuralnetworks.OperandType.FLOAT32;
+  int[] dimensions;
+  float scale;
+  int zeroPoint;
+  android.hardware.neuralnetworks.OperandLifeTime lifetime = android.hardware.neuralnetworks.OperandLifeTime.TEMPORARY_VARIABLE;
+  android.hardware.neuralnetworks.DataLocation location;
+  @nullable android.hardware.neuralnetworks.OperandExtraParams extraParams;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/OperandExtraParams.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/OperandExtraParams.aidl
new file mode 100644
index 0000000..14792cf
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/OperandExtraParams.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@VintfStability
+union OperandExtraParams {
+  android.hardware.neuralnetworks.SymmPerChannelQuantParams channelQuant;
+  byte[] extension;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/OperandLifeTime.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/OperandLifeTime.aidl
new file mode 100644
index 0000000..40adfb1
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/OperandLifeTime.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@Backing(type="int") @VintfStability
+enum OperandLifeTime {
+  TEMPORARY_VARIABLE = 0,
+  SUBGRAPH_INPUT = 1,
+  SUBGRAPH_OUTPUT = 2,
+  CONSTANT_COPY = 3,
+  CONSTANT_POOL = 4,
+  NO_VALUE = 5,
+  SUBGRAPH = 6,
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/OperandPerformance.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/OperandPerformance.aidl
new file mode 100644
index 0000000..ebb361b
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/OperandPerformance.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@VintfStability
+parcelable OperandPerformance {
+  android.hardware.neuralnetworks.OperandType type = android.hardware.neuralnetworks.OperandType.FLOAT32;
+  android.hardware.neuralnetworks.PerformanceInfo info;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/OperandType.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/OperandType.aidl
new file mode 100644
index 0000000..9f2c759
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/OperandType.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@Backing(type="int") @VintfStability
+enum OperandType {
+  FLOAT32 = 0,
+  INT32 = 1,
+  UINT32 = 2,
+  TENSOR_FLOAT32 = 3,
+  TENSOR_INT32 = 4,
+  TENSOR_QUANT8_ASYMM = 5,
+  BOOL = 6,
+  TENSOR_QUANT16_SYMM = 7,
+  TENSOR_FLOAT16 = 8,
+  TENSOR_BOOL8 = 9,
+  FLOAT16 = 10,
+  TENSOR_QUANT8_SYMM_PER_CHANNEL = 11,
+  TENSOR_QUANT16_ASYMM = 12,
+  TENSOR_QUANT8_SYMM = 13,
+  TENSOR_QUANT8_ASYMM_SIGNED = 14,
+  SUBGRAPH = 15,
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Operation.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Operation.aidl
new file mode 100644
index 0000000..a4a3fbe
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Operation.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@VintfStability
+parcelable Operation {
+  android.hardware.neuralnetworks.OperationType type = android.hardware.neuralnetworks.OperationType.ADD;
+  int[] inputs;
+  int[] outputs;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/OperationType.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/OperationType.aidl
new file mode 100644
index 0000000..34506c8
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/OperationType.aidl
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@Backing(type="int") @VintfStability
+enum OperationType {
+  ADD = 0,
+  AVERAGE_POOL_2D = 1,
+  CONCATENATION = 2,
+  CONV_2D = 3,
+  DEPTHWISE_CONV_2D = 4,
+  DEPTH_TO_SPACE = 5,
+  DEQUANTIZE = 6,
+  EMBEDDING_LOOKUP = 7,
+  FLOOR = 8,
+  FULLY_CONNECTED = 9,
+  HASHTABLE_LOOKUP = 10,
+  L2_NORMALIZATION = 11,
+  L2_POOL_2D = 12,
+  LOCAL_RESPONSE_NORMALIZATION = 13,
+  LOGISTIC = 14,
+  LSH_PROJECTION = 15,
+  LSTM = 16,
+  MAX_POOL_2D = 17,
+  MUL = 18,
+  RELU = 19,
+  RELU1 = 20,
+  RELU6 = 21,
+  RESHAPE = 22,
+  RESIZE_BILINEAR = 23,
+  RNN = 24,
+  SOFTMAX = 25,
+  SPACE_TO_DEPTH = 26,
+  SVDF = 27,
+  TANH = 28,
+  BATCH_TO_SPACE_ND = 29,
+  DIV = 30,
+  MEAN = 31,
+  PAD = 32,
+  SPACE_TO_BATCH_ND = 33,
+  SQUEEZE = 34,
+  STRIDED_SLICE = 35,
+  SUB = 36,
+  TRANSPOSE = 37,
+  ABS = 38,
+  ARGMAX = 39,
+  ARGMIN = 40,
+  AXIS_ALIGNED_BBOX_TRANSFORM = 41,
+  BIDIRECTIONAL_SEQUENCE_LSTM = 42,
+  BIDIRECTIONAL_SEQUENCE_RNN = 43,
+  BOX_WITH_NMS_LIMIT = 44,
+  CAST = 45,
+  CHANNEL_SHUFFLE = 46,
+  DETECTION_POSTPROCESSING = 47,
+  EQUAL = 48,
+  EXP = 49,
+  EXPAND_DIMS = 50,
+  GATHER = 51,
+  GENERATE_PROPOSALS = 52,
+  GREATER = 53,
+  GREATER_EQUAL = 54,
+  GROUPED_CONV_2D = 55,
+  HEATMAP_MAX_KEYPOINT = 56,
+  INSTANCE_NORMALIZATION = 57,
+  LESS = 58,
+  LESS_EQUAL = 59,
+  LOG = 60,
+  LOGICAL_AND = 61,
+  LOGICAL_NOT = 62,
+  LOGICAL_OR = 63,
+  LOG_SOFTMAX = 64,
+  MAXIMUM = 65,
+  MINIMUM = 66,
+  NEG = 67,
+  NOT_EQUAL = 68,
+  PAD_V2 = 69,
+  POW = 70,
+  PRELU = 71,
+  QUANTIZE = 72,
+  QUANTIZED_16BIT_LSTM = 73,
+  RANDOM_MULTINOMIAL = 74,
+  REDUCE_ALL = 75,
+  REDUCE_ANY = 76,
+  REDUCE_MAX = 77,
+  REDUCE_MIN = 78,
+  REDUCE_PROD = 79,
+  REDUCE_SUM = 80,
+  ROI_ALIGN = 81,
+  ROI_POOLING = 82,
+  RSQRT = 83,
+  SELECT = 84,
+  SIN = 85,
+  SLICE = 86,
+  SPLIT = 87,
+  SQRT = 88,
+  TILE = 89,
+  TOPK_V2 = 90,
+  TRANSPOSE_CONV_2D = 91,
+  UNIDIRECTIONAL_SEQUENCE_LSTM = 92,
+  UNIDIRECTIONAL_SEQUENCE_RNN = 93,
+  RESIZE_NEAREST_NEIGHBOR = 94,
+  QUANTIZED_LSTM = 95,
+  IF = 96,
+  WHILE = 97,
+  ELU = 98,
+  HARD_SWISH = 99,
+  FILL = 100,
+  RANK = 101,
+  BATCH_MATMUL = 102,
+  PACK = 103,
+  MIRROR_PAD = 104,
+  REVERSE = 105,
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/OutputShape.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/OutputShape.aidl
new file mode 100644
index 0000000..f733505
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/OutputShape.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@VintfStability
+parcelable OutputShape {
+  int[] dimensions;
+  boolean isSufficient;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/PerformanceInfo.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/PerformanceInfo.aidl
new file mode 100644
index 0000000..04910f5
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/PerformanceInfo.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@VintfStability
+parcelable PerformanceInfo {
+  float execTime;
+  float powerUsage;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Priority.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Priority.aidl
new file mode 100644
index 0000000..8f35709
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Priority.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@Backing(type="int") @VintfStability
+enum Priority {
+  LOW = 0,
+  MEDIUM = 1,
+  HIGH = 2,
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Request.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Request.aidl
new file mode 100644
index 0000000..39ec7a9
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Request.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@VintfStability
+parcelable Request {
+  android.hardware.neuralnetworks.RequestArgument[] inputs;
+  android.hardware.neuralnetworks.RequestArgument[] outputs;
+  android.hardware.neuralnetworks.RequestMemoryPool[] pools;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/RequestArgument.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/RequestArgument.aidl
new file mode 100644
index 0000000..e3541c0
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/RequestArgument.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@VintfStability
+parcelable RequestArgument {
+  boolean hasNoValue;
+  android.hardware.neuralnetworks.DataLocation location;
+  int[] dimensions;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/RequestMemoryPool.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/RequestMemoryPool.aidl
new file mode 100644
index 0000000..312f581
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/RequestMemoryPool.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@VintfStability
+union RequestMemoryPool {
+  android.hardware.neuralnetworks.Memory pool;
+  int token;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Subgraph.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Subgraph.aidl
new file mode 100644
index 0000000..b7d4451
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Subgraph.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@VintfStability
+parcelable Subgraph {
+  android.hardware.neuralnetworks.Operand[] operands;
+  android.hardware.neuralnetworks.Operation[] operations;
+  int[] inputIndexes;
+  int[] outputIndexes;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/SymmPerChannelQuantParams.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/SymmPerChannelQuantParams.aidl
new file mode 100644
index 0000000..02d68f9
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/SymmPerChannelQuantParams.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@VintfStability
+parcelable SymmPerChannelQuantParams {
+  float[] scales;
+  int channelDim;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Timing.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Timing.aidl
new file mode 100644
index 0000000..bcc83cf
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/3/android/hardware/neuralnetworks/Timing.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.neuralnetworks;
+@VintfStability
+parcelable Timing {
+  long timeOnDeviceNs;
+  long timeInDriverNs;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExecutionConfig.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExecutionConfig.aidl
new file mode 100644
index 0000000..cb85743
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/ExecutionConfig.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+parcelable ExecutionConfig {
+  boolean measureTiming;
+  long loopTimeoutDurationNs;
+  android.hardware.neuralnetworks.TokenValuePair[] executionHints;
+  android.hardware.neuralnetworks.ExtensionNameAndPrefix[] extensionNameToPrefix;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IBurst.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IBurst.aidl
index eb3d0b0..461fdfa 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IBurst.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IBurst.aidl
@@ -36,4 +36,5 @@
 interface IBurst {
   android.hardware.neuralnetworks.ExecutionResult executeSynchronously(in android.hardware.neuralnetworks.Request request, in long[] memoryIdentifierTokens, in boolean measureTiming, in long deadlineNs, in long loopTimeoutDurationNs);
   void releaseMemoryResource(in long memoryIdentifierToken);
+  android.hardware.neuralnetworks.ExecutionResult executeSynchronouslyWithConfig(in android.hardware.neuralnetworks.Request request, in long[] memoryIdentifierTokens, in android.hardware.neuralnetworks.ExecutionConfig config, in long deadlineNs);
 }
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IDevice.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IDevice.aidl
index c9c67f2..c0fba47 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IDevice.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IDevice.aidl
@@ -43,6 +43,7 @@
   String getVersionString();
   void prepareModel(in android.hardware.neuralnetworks.Model model, in android.hardware.neuralnetworks.ExecutionPreference preference, in android.hardware.neuralnetworks.Priority priority, in long deadlineNs, in ParcelFileDescriptor[] modelCache, in ParcelFileDescriptor[] dataCache, in byte[] token, in android.hardware.neuralnetworks.IPreparedModelCallback callback);
   void prepareModelFromCache(in long deadlineNs, in ParcelFileDescriptor[] modelCache, in ParcelFileDescriptor[] dataCache, in byte[] token, in android.hardware.neuralnetworks.IPreparedModelCallback callback);
+  void prepareModelWithConfig(in android.hardware.neuralnetworks.Model model, in android.hardware.neuralnetworks.PrepareModelConfig config, in android.hardware.neuralnetworks.IPreparedModelCallback callback);
   const int BYTE_SIZE_OF_CACHE_TOKEN = 32;
   const int MAX_NUMBER_OF_CACHE_FILES = 32;
   const int EXTENSION_TYPE_HIGH_BITS_PREFIX = 15;
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IExecution.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IExecution.aidl
new file mode 100644
index 0000000..ab5275e
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IExecution.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+interface IExecution {
+  android.hardware.neuralnetworks.ExecutionResult executeSynchronously(in long deadlineNs);
+  android.hardware.neuralnetworks.FencedExecutionResult executeFenced(in ParcelFileDescriptor[] waitFor, in long deadlineNs, in long durationNs);
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IPreparedModel.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IPreparedModel.aidl
index fccb5dc..fb0c372 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IPreparedModel.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/IPreparedModel.aidl
@@ -37,6 +37,9 @@
   android.hardware.neuralnetworks.ExecutionResult executeSynchronously(in android.hardware.neuralnetworks.Request request, in boolean measureTiming, in long deadlineNs, in long loopTimeoutDurationNs);
   android.hardware.neuralnetworks.FencedExecutionResult executeFenced(in android.hardware.neuralnetworks.Request request, in ParcelFileDescriptor[] waitFor, in boolean measureTiming, in long deadlineNs, in long loopTimeoutDurationNs, in long durationNs);
   android.hardware.neuralnetworks.IBurst configureExecutionBurst();
+  android.hardware.neuralnetworks.IExecution createReusableExecution(in android.hardware.neuralnetworks.Request request, in android.hardware.neuralnetworks.ExecutionConfig config);
+  android.hardware.neuralnetworks.ExecutionResult executeSynchronouslyWithConfig(in android.hardware.neuralnetworks.Request request, in android.hardware.neuralnetworks.ExecutionConfig config, in long deadlineNs);
+  android.hardware.neuralnetworks.FencedExecutionResult executeFencedWithConfig(in android.hardware.neuralnetworks.Request request, in ParcelFileDescriptor[] waitFor, in android.hardware.neuralnetworks.ExecutionConfig config, in long deadlineNs, in long durationNs);
   const long DEFAULT_LOOP_TIMEOUT_DURATION_NS = 2000000000;
   const long MAXIMUM_LOOP_TIMEOUT_DURATION_NS = 15000000000;
 }
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperationType.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperationType.aidl
index 2eff11b..34506c8 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperationType.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperationType.aidl
@@ -138,4 +138,6 @@
   RANK = 101,
   BATCH_MATMUL = 102,
   PACK = 103,
+  MIRROR_PAD = 104,
+  REVERSE = 105,
 }
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/PrepareModelConfig.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/PrepareModelConfig.aidl
new file mode 100644
index 0000000..1f44ba7
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/PrepareModelConfig.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+parcelable PrepareModelConfig {
+  android.hardware.neuralnetworks.ExecutionPreference preference;
+  android.hardware.neuralnetworks.Priority priority;
+  long deadlineNs;
+  ParcelFileDescriptor[] modelCache;
+  ParcelFileDescriptor[] dataCache;
+  byte[32] cacheToken;
+  android.hardware.neuralnetworks.TokenValuePair[] compilationHints;
+  android.hardware.neuralnetworks.ExtensionNameAndPrefix[] extensionNameToPrefix;
+  const int BYTE_SIZE_OF_CACHE_TOKEN = 32;
+}
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/TokenValuePair.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/TokenValuePair.aidl
new file mode 100644
index 0000000..e477d6e
--- /dev/null
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/TokenValuePair.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.neuralnetworks;
+@VintfStability
+parcelable TokenValuePair {
+  int token;
+  byte[] value;
+}
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/ExecutionConfig.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/ExecutionConfig.aidl
new file mode 100644
index 0000000..00f1e11
--- /dev/null
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/ExecutionConfig.aidl
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.neuralnetworks;
+
+import android.hardware.neuralnetworks.ExtensionNameAndPrefix;
+import android.hardware.neuralnetworks.TokenValuePair;
+
+/**
+ * A type that is used to represent all configuration related to
+ * an Execution.
+ */
+@VintfStability
+parcelable ExecutionConfig {
+    /**
+     * Specifies whether or not to measure duration of the execution.
+     * For {@link IPreparedModel::executeSynchronouslyWithConfig}, the duration runs from the time
+     * the driver sees the corresponding call to the execute function to the time the driver returns
+     * from the function. For {@link IPreparedModel::executeFencedWithConfig}, please refer to
+     * {@link IPreparedModelCallback} for details.
+     */
+    boolean measureTiming;
+    /**
+     * The maximum amount of time in nanoseconds that should be spent
+     * executing a {@link OperationType::WHILE} operation. If a loop
+     * condition model does not output false within this duration,
+     * the execution must be aborted. If -1 is provided, the maximum
+     * amount of time is {@link DEFAULT_LOOP_TIMEOUT_DURATION_NS}.
+     * Other negative values are invalid. When provided, the duration
+     * must not exceed {@link MAXIMUM_LOOP_TIMEOUT_DURATION_NS}.
+     */
+    long loopTimeoutDurationNs;
+    /**
+     * A vector of token / value pairs represent vendor specific
+     * execution hints or metadata. The provided TokenValuePairs must not
+     * contain the same token twice. The driver must validate the
+     * data and ignore invalid hints. It is up to the driver to
+     * decide whether to respect the provided hints or not.
+     */
+    TokenValuePair[] executionHints;
+    /**
+     * The mapping between extension names and prefixes of token values.
+     * The driver must ignore the corresponding execution hint, if
+     * the extension is not supported.
+     */
+    ExtensionNameAndPrefix[] extensionNameToPrefix;
+}
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/Extension.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/Extension.aidl
index 20109bd..9f70a53 100644
--- a/neuralnetworks/aidl/android/hardware/neuralnetworks/Extension.aidl
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/Extension.aidl
@@ -20,6 +20,10 @@
 
 /**
  * Information about an extension.
+ *
+ * The extension can provide zero or more operation types (which are not enumerated), zero or more
+ * operand types (which are enumerated in {@link Extension::operandTypes}, and compilation and
+ * execution hints (which are not enumerated).
  */
 @VintfStability
 parcelable Extension {
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/ExtensionNameAndPrefix.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/ExtensionNameAndPrefix.aidl
index 29be93f..6c296e0 100644
--- a/neuralnetworks/aidl/android/hardware/neuralnetworks/ExtensionNameAndPrefix.aidl
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/ExtensionNameAndPrefix.aidl
@@ -17,7 +17,8 @@
 package android.hardware.neuralnetworks;
 
 /**
- * The mapping between extension names and prefixes of operand and operation type values.
+ * The mapping between extension names and prefixes of values like operand and operation type, and
+ * token in {@link TokenValuePair}.
  *
  * An operand or operation whose numeric type value is above {@link IDevice::OPERAND_TYPE_BASE_MAX}
  * or {@link IDevice::OPERATION_TYPE_BASE_MAX} respectively should be interpreted as an extension
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/IBurst.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/IBurst.aidl
index decdc48..a05a7fb 100644
--- a/neuralnetworks/aidl/android/hardware/neuralnetworks/IBurst.aidl
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/IBurst.aidl
@@ -17,6 +17,7 @@
 package android.hardware.neuralnetworks;
 
 import android.hardware.neuralnetworks.ErrorStatus;
+import android.hardware.neuralnetworks.ExecutionConfig;
 import android.hardware.neuralnetworks.ExecutionResult;
 import android.hardware.neuralnetworks.Request;
 
@@ -68,6 +69,8 @@
      *
      * Only a single execution on a given burst object may be active at any time.
      *
+     * Also see {@link IBurst::executeSynchronouslyWithConfig}.
+     *
      * @param request The input and output information on which the prepared model is to be
      *                executed.
      * @param memoryIdentifierTokens A list of tokens where each token is a non-negative number
@@ -78,10 +81,10 @@
      *                runs from the time the driver sees the call to the executeSynchronously
      *                function to the time the driver returns from the function.
      * @param deadlineNs The time by which the execution is expected to complete. The time is
-     *                   measured in nanoseconds since epoch of the steady clock (as from
-     *                   std::chrono::steady_clock). If the execution cannot be finished by the
-     *                   deadline, the execution may be aborted. Passing -1 means the deadline is
-     *                   omitted. Other negative values are invalid.
+     *                   measured in nanoseconds since boot (as from clock_gettime(CLOCK_BOOTTIME,
+     *                   &ts) or ::android::base::boot_clock). If the execution cannot be finished
+     *                   by the deadline, the execution may be aborted. Passing -1 means the
+     *                   deadline is omitted. Other negative values are invalid.
      * @param loopTimeoutDurationNs The maximum amount of time in nanoseconds that should be spent
      *                              executing a {@link OperationType::WHILE} operation. If a loop
      *                              condition model does not output false within this duration, the
@@ -117,4 +120,13 @@
      *     - INVALID_ARGUMENT if one of the input arguments is invalid
      */
     void releaseMemoryResource(in long memoryIdentifierToken);
+
+    /**
+     * For detailed specification, please refer to {@link IBurst::executeSynchronously}. The
+     * difference between the two methods is that executeSynchronouslyWithConfig takes {@link
+     * ExecutionConfig} instead of a list of configuration parameters, and ExecutionConfig contains
+     * more configuration parameters than are passed to executeSynchronously.
+     */
+    ExecutionResult executeSynchronouslyWithConfig(in Request request,
+            in long[] memoryIdentifierTokens, in ExecutionConfig config, in long deadlineNs);
 }
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/IDevice.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/IDevice.aidl
index 72e2623..7808fc2 100644
--- a/neuralnetworks/aidl/android/hardware/neuralnetworks/IDevice.aidl
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/IDevice.aidl
@@ -28,6 +28,7 @@
 import android.hardware.neuralnetworks.IPreparedModelParcel;
 import android.hardware.neuralnetworks.Model;
 import android.hardware.neuralnetworks.NumberOfCacheFiles;
+import android.hardware.neuralnetworks.PrepareModelConfig;
 import android.hardware.neuralnetworks.Priority;
 
 /**
@@ -38,7 +39,7 @@
     /**
      * The byte size of the cache token.
      */
-    const int BYTE_SIZE_OF_CACHE_TOKEN = 32;
+    const int BYTE_SIZE_OF_CACHE_TOKEN = PrepareModelConfig.BYTE_SIZE_OF_CACHE_TOKEN;
     /**
      * The maximum number of files for each type of cache in compilation caching.
      */
@@ -148,7 +149,7 @@
      *
      * If the device reports that caching is not supported, the user may avoid calling
      * IDevice::prepareModelFromCache or providing cache file descriptors to
-     * IDevice::prepareModel.
+     * IDevice::prepareModel or IDevice::prepareModelWithConfig.
      *
      * @return NumberOfCacheFiles structure indicating how many files for model and data cache the
      *     driver needs to cache a single prepared model. It must be less than or equal to
@@ -302,6 +303,8 @@
      *
      * Multiple threads may call prepareModel on the same model concurrently.
      *
+     * Also see {@link IDevice::prepareModelWithConfig}.
+     *
      * @param model The model to be prepared for execution.
      * @param preference Indicates the intended execution behavior of a prepared model.
      * @param priority The priority of the prepared model relative to other prepared models owned by
@@ -403,17 +406,17 @@
      * @param modelCache A vector of file descriptors for the security-sensitive cache. The length
      *                   of the vector must match the numModelCache returned from
      *                   getNumberOfCacheFilesNeeded. The cache file descriptors will be provided in
-     *                   the same order as with prepareModel.
+     *                   the same order as with prepareModel or prepareModelWithConfig.
      * @param dataCache A vector of file descriptors for the constants' cache. The length of the
      *                  vector must match the numDataCache returned from
      *                  getNumberOfCacheFilesNeeded. The cache file descriptors will be provided in
-     *                  the same order as with prepareModel.
+     *                  the same order as with prepareModel or prepareModelWithConfig.
      * @param token A caching token of length BYTE_SIZE_OF_CACHE_TOKEN identifying the prepared
      *              model. It is the same token provided when saving the cache files with
-     *              prepareModel. Tokens should be chosen to have a low rate of collision for a
-     *              particular application. The driver cannot detect a collision; a collision will
-     *              result in a failed execution or in a successful execution that produces
-     *              incorrect output values.
+     *              prepareModel or prepareModelWithConfig. Tokens should be chosen to have a low
+     *              rate of collision for a particular application. The driver cannot detect a
+     *              collision; a collision will result in a failed execution or in a successful
+     *              execution that produces incorrect output values.
      * @param callback A callback object used to return the error status of preparing the model for
      *                 execution and the prepared model if successful, nullptr otherwise. The
      *                 callback object's notify function must be called exactly once, even if the
@@ -429,4 +432,28 @@
     void prepareModelFromCache(in long deadlineNs, in ParcelFileDescriptor[] modelCache,
             in ParcelFileDescriptor[] dataCache, in byte[] token,
             in IPreparedModelCallback callback);
+
+    /**
+     * For detailed specification, please refer to {@link IDevice::prepareModel}. The only
+     * difference between the two methods is that prepareModelWithConfig takes {@link
+     * PrepareModelConfig} instead of standalone configuration parameters, which allows vendor
+     * specific compilation metadata to be passed.
+     *
+     * @param model The model to be prepared for execution.
+     * @param config Configuration parameters to prepare the model.
+     * @param callback A callback object used to return the error status of preparing the model for
+     *                 execution and the prepared model if successful, nullptr otherwise. The
+     *                 callback object's notify function must be called exactly once, even if the
+     *                 model could not be prepared.
+     * @throws ServiceSpecificException with one of the following ErrorStatus values:
+     *     - DEVICE_UNAVAILABLE if driver is offline or busy
+     *     - GENERAL_FAILURE if there is an unspecified error
+     *     - INVALID_ARGUMENT if one of the input arguments related to preparing the model is
+     *       invalid
+     *     - MISSED_DEADLINE_* if the preparation is aborted because the model cannot be prepared by
+     *       the deadline
+     *     - RESOURCE_EXHAUSTED_* if the task was aborted by the driver
+     */
+    void prepareModelWithConfig(
+            in Model model, in PrepareModelConfig config, in IPreparedModelCallback callback);
 }
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/IExecution.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/IExecution.aidl
new file mode 100644
index 0000000..3cb9c1a
--- /dev/null
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/IExecution.aidl
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.neuralnetworks;
+
+import android.hardware.neuralnetworks.ExecutionResult;
+import android.hardware.neuralnetworks.FencedExecutionResult;
+
+/**
+ * IExecution represents a reusable execution object with request and most other execution
+ * properties fixed. It is used to launch executions.
+ *
+ * At most one execution may occur on a reusable execution object at any given time, either by
+ * means of executeSynchronously or executeFenced.
+ *
+ * An IExecution object is used to control a set of executions on the same prepared model with
+ * the same request and properties. IExecution objects enable some optimizations:
+ * (1) An IExecution object can preserve resources between executions. For example, a driver can
+ *     map a memory object when the IExecution object is created and cache the mapping for reuse in
+ *     subsequent executions. Any cached resource can be released when the IExecution object is
+ *     destroyed.
+ * (2) Because an IExecution object may be used for at most one execution at a time, any transient
+ *     execution resources such as intermediate tensors can be allocated once when the IExecution
+ *     object is created and freed when the IExecution object is destroyed.
+ * (3) An IExecution object is created for a fixed request. This enables the implementation to apply
+ *     request-specific optimizations. For example, an implementation can avoid request validation
+ *     and conversions when the IExecution object is reused. An implementation may also choose to
+ *     specialize the dynamic tensor shapes in the IExecution object according to the request.
+ */
+@VintfStability
+interface IExecution {
+    /**
+     * Performs a synchronous execution on the reusable execution object.
+     *
+     * The execution is performed synchronously with respect to the caller. executeSynchronously
+     * must verify the inputs to the function are correct, and the usages of memory pools allocated
+     * by IDevice::allocate are valid. If there is an error, executeSynchronously must immediately
+     * return a service specific exception with the appropriate ErrorStatus value. If the inputs to
+     * the function are valid and there is no error, executeSynchronously must perform the
+     * execution, and must not return until the execution is complete.
+     *
+     * The caller must not change the content of any data object referenced by the 'request'
+     * provided in {@link IPreparedModel::createReusableExecution} (described by the
+     * {@link DataLocation} of a {@link RequestArgument}) until executeSynchronously returns.
+     * executeSynchronously must not change the content of any of the data objects corresponding to
+     * 'request' inputs.
+     *
+     * If the execution object was configured from a prepared model wherein all tensor operands have
+     * fully specified dimensions, and the inputs to the function are valid, and at execution time
+     * every operation's input operands have legal values, then the execution should complete
+     * successfully: there must be no failure unless the device itself is in a bad state.
+     *
+     * If the execution object was created with measureTiming being true and the execution is
+     * successful, the driver may report the timing information in the returning
+     * {@link ExecutionResult}. The duration runs from the time the driver sees the call to the time
+     * the driver returns from the function.
+     *
+     * executeSynchronously may be called with an optional deadline. If the execution is not able to
+     * be completed before the provided deadline, the execution may be aborted, and either
+     * {@link ErrorStatus::MISSED_DEADLINE_TRANSIENT} or {@link
+     * ErrorStatus::MISSED_DEADLINE_PERSISTENT} may be returned. The error due to an abort must be
+     * sent the same way as other errors, described above.
+     *
+     * @param deadlineNs The time by which the execution is expected to complete. The time is
+     *                   measured in nanoseconds since boot (as from clock_gettime(CLOCK_BOOTTIME,
+     *                   &ts) or ::android::base::boot_clock). If the execution cannot be finished
+     *                   by the deadline, the execution may be aborted. Passing -1 means the
+     *                   deadline is omitted. Other negative values are invalid.
+     * @return ExecutionResult parcelable, containing the status of the execution, output shapes
+     *     and timing information.
+     * @throws ServiceSpecificException with one of the following ErrorStatus values:
+     *     - DEVICE_UNAVAILABLE if driver is offline or busy
+     *     - GENERAL_FAILURE if there is an unspecified error
+     *     - INVALID_ARGUMENT if one of the input arguments is invalid
+     *     - MISSED_DEADLINE_* if the execution is aborted because it cannot be completed by the
+     *       deadline
+     *     - RESOURCE_EXHAUSTED_* if the task was aborted by the driver
+     */
+    ExecutionResult executeSynchronously(in long deadlineNs);
+
+    /**
+     * Launch a fenced asynchronous execution on the reusable execution object.
+     *
+     * The execution is performed asynchronously with respect to the caller. executeFenced must
+     * verify the inputs to the function are correct, and the usages of memory pools allocated by
+     * IDevice::allocate are valid. If there is an error, executeFenced must immediately return a
+     * service specific exception with the corresponding ErrorStatus. If the inputs to the function
+     * are valid and there is no error, executeFenced must dispatch an asynchronous task to perform
+     * the execution in the background, and immediately return a {@link FencedExecutionResult}
+     * containing two fields: a callback (which can be used by the client to query the duration and
+     * runtime error status) and a sync fence (which will be signaled once the execution is
+     * completed). If the task has finished before the call returns, syncFence file descriptor may
+     * be set to -1. The execution must wait for all the sync fences (if any) in waitFor to be
+     * signaled before starting the actual execution.
+     *
+     * When the asynchronous task has finished its execution, it must immediately signal the
+     * syncFence returned from the executeFenced call. After the syncFence is signaled, the task
+     * must not modify the content of any data object referenced by the 'request' provided in
+     * IPreparedModel::createReusableExecution (described by the {@link DataLocation} of a
+     * {@link RequestArgument}).
+     *
+     * executeFenced may be called with an optional deadline and an optional duration. If the
+     * execution is not able to be completed before the provided deadline or within the timeout
+     * duration (measured from when all sync fences in waitFor are signaled), whichever comes
+     * earlier, the execution may be aborted, and either
+     * {@link ErrorStatus::MISSED_DEADLINE_TRANSIENT} or {@link
+     * ErrorStatus::MISSED_DEADLINE_PERSISTENT} may be returned. The error due to an abort must be
+     * sent the same way as other errors, described above.
+     *
+     * If any of the sync fences in waitFor changes to error status after the executeFenced call
+     * succeeds, or the execution is aborted because it cannot finish before the deadline has been
+     * reached or the duration has elapsed, the driver must immediately set the returned syncFence
+     * to error status.
+     *
+     * @param waitFor A vector of sync fence file descriptors. Execution must not start until all
+     *                sync fences have been signaled.
+     * @param deadlineNs The time by which the execution is expected to complete. The time is
+     *                   measured in nanoseconds since boot (as from clock_gettime(CLOCK_BOOTTIME,
+     *                   &ts) or ::android::base::boot_clock). If the execution cannot be finished
+     *                   by the deadline, the execution may be aborted. Passing -1 means the
+     *                   deadline is omitted. Other negative values are invalid.
+     * @param durationNs The length of time in nanoseconds within which the execution is expected
+     *                   to complete after all sync fences in waitFor are signaled. If the
+     *                   execution cannot be finished within the duration, the execution may be
+     *                   aborted. Passing -1 means the duration is omitted. Other negative values
+     *                   are invalid.
+     * @return The FencedExecutionResult parcelable, containing IFencedExecutionCallback and the
+     *         sync fence.
+     * @throws ServiceSpecificException with one of the following ErrorStatus values:
+     *     - DEVICE_UNAVAILABLE if driver is offline or busy
+     *     - GENERAL_FAILURE if there is an unspecified error
+     *     - INVALID_ARGUMENT if one of the input arguments is invalid, including fences in error
+     *       states.
+     *     - MISSED_DEADLINE_* if the execution is aborted because it cannot be completed by the
+     *       deadline
+     *     - RESOURCE_EXHAUSTED_* if the task was aborted by the driver
+     */
+    FencedExecutionResult executeFenced(
+            in ParcelFileDescriptor[] waitFor, in long deadlineNs, in long durationNs);
+}
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/IPreparedModel.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/IPreparedModel.aidl
index 956b626..f752750 100644
--- a/neuralnetworks/aidl/android/hardware/neuralnetworks/IPreparedModel.aidl
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/IPreparedModel.aidl
@@ -18,9 +18,11 @@
 
 import android.hardware.common.NativeHandle;
 import android.hardware.neuralnetworks.ErrorStatus;
+import android.hardware.neuralnetworks.ExecutionConfig;
 import android.hardware.neuralnetworks.ExecutionResult;
 import android.hardware.neuralnetworks.FencedExecutionResult;
 import android.hardware.neuralnetworks.IBurst;
+import android.hardware.neuralnetworks.IExecution;
 import android.hardware.neuralnetworks.Request;
 
 /**
@@ -67,6 +69,8 @@
      * Any number of calls to the execute* functions, in any combination, may be made concurrently,
      * even on the same IPreparedModel object.
      *
+     * Also see {@link IPreparedModel::executeSynchronouslyWithConfig}.
+     *
      * @param request The input and output information on which the prepared model is to be
      *                executed.
      * @param measure Specifies whether or not to measure duration of the execution. The duration
@@ -105,11 +109,12 @@
      * IDevice::allocate are valid. If there is an error, executeFenced must immediately return a
      * service specific exception with the corresponding ErrorStatus. If the inputs to the function
      * are valid and there is no error, executeFenced must dispatch an asynchronous task to perform
-     * the execution in the background, assign a sync fence that will be signaled once the execution
-     * is completed and immediately return a callback that can be used by the client to query the
-     * duration and runtime error status. If the task has finished before the call returns,
-     * syncFence file descriptor may be set to -1. The execution must wait for all the sync fences
-     * (if any) in waitFor to be signaled before starting the actual execution.
+     * the execution in the background, and immediately return a {@link FencedExecutionResult}
+     * containing two fields: a callback (which can be used by the client to query the duration and
+     * runtime error status) and a sync fence (which will be signaled once the execution is
+     * completed). If the task has finished before the call returns, syncFence file descriptor may
+     * be set to -1. The execution must wait for all the sync fences (if any) in waitFor to be
+     * signaled before starting the actual execution.
      *
      * When the asynchronous task has finished its execution, it must immediately signal the
      * syncFence returned from the executeFenced call. After the syncFence is signaled, the task
@@ -132,6 +137,8 @@
      * Any number of calls to the execute* functions, in any combination, may be made concurrently,
      * even on the same IPreparedModel object.
      *
+     * Also see {@link IPreparedModel::executeFencedWithConfig}.
+     *
      * @param request The input and output information on which the prepared model is to be
      *                executed. The outputs in the request must have fully specified dimensions.
      * @param waitFor A vector of sync fence file descriptors. Execution must not start until all
@@ -186,4 +193,100 @@
      *     - RESOURCE_EXHAUSTED_* if the task was aborted by the driver
      */
     IBurst configureExecutionBurst();
+
+    /**
+     * Create a reusable execution object to launch multiple executions with the same request and
+     * properties.
+     *
+     * createReusableExecution must verify the inputs to the function are correct, and the usages of
+     * memory pools allocated by IDevice::allocate are valid. If there is an error,
+     * createReusableExecution must immediately return a service specific exception with the
+     * appropriate ErrorStatus value. If the inputs to the function are valid and there is no error,
+     * createReusableExecution must construct a reusable execution.
+     *
+     * This method will be called when a client requests a reusable execution with consistent
+     * request and execution config. For single-time execution,
+     * {@link IPreparedModel::executeSynchronouslyWithConfig} or
+     * {@link IPreparedModel::executeFencedWithConfig} is preferred, because the overhead of
+     * setting up a reusable execution can be avoided.
+     *
+     * @param request The input and output information on which the prepared model is to be
+     *                executed.
+     * @param config Specifies the execution configuration parameters.
+     * @return execution An IExecution object representing a reusable execution that has been
+     *                   specialized for a fixed request.
+     * @throws ServiceSpecificException with one of the following ErrorStatus values:
+     *     - DEVICE_UNAVAILABLE if driver is offline or busy
+     *     - GENERAL_FAILURE if there is an unspecified error
+     *     - INVALID_ARGUMENT if one of the input arguments is invalid
+     *     - RESOURCE_EXHAUSTED_* if the task was aborted by the driver
+     */
+    IExecution createReusableExecution(in Request request, in ExecutionConfig config);
+
+    /**
+     * For detailed specification, please refer to {@link IPreparedModel::executeSynchronously}. The
+     * difference between the two methods is that executeSynchronouslyWithConfig takes {@link
+     * ExecutionConfig} instead of a list of configuration parameters, and ExecutionConfig contains
+     * more configuration parameters than are passed to executeSynchronously.
+     *
+     * This method is preferred when a client requests a single-time synchronous execution.
+     * For reusable execution with consistent request and execution config,
+     * {@link IPreparedModel::createReusableExecution} must be called.
+     *
+     * @param request The input and output information on which the prepared model is to be
+     *                executed.
+     * @param config Specifies the execution configuration parameters.
+     * @param deadlineNs The time by which the execution is expected to complete. The time is
+     *                   measured in nanoseconds since boot (as from clock_gettime(CLOCK_BOOTTIME,
+     *                   &ts) or ::android::base::boot_clock). If the execution cannot be finished
+     *                   by the deadline, the execution may be aborted. Passing -1 means the
+     *                   deadline is omitted. Other negative valueggs are invalid.
+     * @return ExecutionResult parcelable, containing the status of the execution, output shapes and
+     *     timing information.
+     *     - MISSED_DEADLINE_* if the execution is aborted because it cannot be completed by the
+     *       deadline
+     *     - RESOURCE_EXHAUSTED_* if the task was aborted by the driver
+     */
+    ExecutionResult executeSynchronouslyWithConfig(
+            in Request request, in ExecutionConfig config, in long deadlineNs);
+
+    /**
+     * For detailed specification, please refer to {@link IPreparedModel::executeFenced}. The
+     * difference between the two methods is that executeFencedWithConfig takes {@link
+     * ExecutionConfig} instead of a list of configuration parameters, and ExecutionConfig contains
+     * more configuration parameters than are passed to executeFenced.
+     *
+     * This method is preferred when a client requests a single-time fenced execution.
+     * For reusable execution with consistent request and execution config,
+     * {@link IPreparedModel::createReusableExecution} must be called.
+     *
+     * @param request The input and output information on which the prepared model is to be
+     *                executed. The outputs in the request must have fully specified dimensions.
+     * @param waitFor A vector of sync fence file descriptors. Execution must not start until all
+     *                sync fences have been signaled.
+     * @param config Specifies the execution configuration parameters.
+     * @param deadlineNs The time by which the execution is expected to complete. The time is
+     *                   measured in nanoseconds since boot (as from clock_gettime(CLOCK_BOOTTIME,
+     *                   &ts) or ::android::base::boot_clock). If the execution cannot be finished
+     *                   by the deadline, the execution may be aborted. Passing -1 means the
+     *                   deadline is omitted. Other negative values are invalid.
+     * @param durationNs The length of time in nanoseconds within which the execution is expected to
+     *                   complete after all sync fences in waitFor are signaled. If the execution
+     *                   cannot be finished within the duration, the execution may be aborted.
+     *                   Passing -1 means the duration is omitted. Other negative values are
+     *                   invalid.
+     * @return The FencedExecutionResult parcelable, containing IFencedExecutionCallback and the
+     *         sync fence.
+     * @throws ServiceSpecificException with one of the following ErrorStatus values:
+     *     - DEVICE_UNAVAILABLE if driver is offline or busy
+     *     - GENERAL_FAILURE if there is an unspecified error
+     *     - INVALID_ARGUMENT if one of the input arguments is invalid, including fences in error
+     *       states.
+     *     - MISSED_DEADLINE_* if the execution is aborted because it cannot be completed by the
+     *       deadline
+     *     - RESOURCE_EXHAUSTED_* if the task was aborted by the driver
+     */
+    FencedExecutionResult executeFencedWithConfig(in Request request,
+            in ParcelFileDescriptor[] waitFor, in ExecutionConfig config, in long deadlineNs,
+            in long durationNs);
 }
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/OperandType.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/OperandType.aidl
index 12edc0f..dfda1d2 100644
--- a/neuralnetworks/aidl/android/hardware/neuralnetworks/OperandType.aidl
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/OperandType.aidl
@@ -24,35 +24,30 @@
  * Types prefaced with TENSOR_* must be used for tensor data (i.e., tensors
  * with at least one dimension). Types not prefaced by TENSOR_* represent
  * scalar values and must have no dimensions.
+ *
+ * Although we define many types, most operators accept just a few
+ * types. Most used are {@link OperandType::TENSOR_FLOAT32},
+ * {@link OperandType::TENSOR_QUANT8_ASYMM},
+ * and {@link OperandType::INT32}.
  */
 @VintfStability
 @Backing(type="int")
 enum OperandType {
-    /**
-     * A 32 bit floating point scalar value.
-     */
+    /** A 32 bit floating point scalar value. */
     FLOAT32 = 0,
-    /**
-     * A signed 32 bit integer scalar value.
-     */
+    /** A signed 32 bit integer scalar value. */
     INT32 = 1,
-    /**
-     * An unsigned 32 bit integer scalar value.
-     */
+    /** An unsigned 32 bit integer scalar value. */
     UINT32 = 2,
-    /**
-     * A tensor of 32 bit floating point values.
-     */
+    /** A tensor of 32 bit floating point values. */
     TENSOR_FLOAT32 = 3,
-    /**
-     * A tensor of 32 bit integer values.
-     */
+    /** A tensor of 32 bit integer values. */
     TENSOR_INT32 = 4,
     /**
      * A tensor of 8 bit unsigned integers that represent real numbers.
      *
-     * Attached to this tensor are two numbers that can be used to convert the 8 bit integer to the
-     * real value and vice versa. These two numbers are:
+     * Attached to this tensor are two numbers that can be used to convert the
+     * 8 bit integer to the real value and vice versa. These two numbers are:
      * - scale: a 32 bit floating point value greater than zero.
      * - zeroPoint: a 32 bit integer, in range [0, 255].
      *
@@ -63,15 +58,15 @@
     /**
      * An 8 bit boolean scalar value.
      *
-     * Values of this operand type are either true or false. A zero value represents false; any
-     * other value represents true.
+     * Values of this operand type are either true or false. A zero value
+     * represents false; any other value represents true.
      */
     BOOL = 6,
     /**
      * A tensor of 16 bit signed integers that represent real numbers.
      *
-     * Attached to this tensor is a number representing real value scale that is used to convert the
-     * 16 bit number to a real value in the following way:
+     * Attached to this tensor is a number representing real value scale that is
+     * used to convert the 16 bit number to a real value in the following way:
      * realValue = integerValue * scale.
      *
      * scale is a 32 bit floating point with value greater than zero.
@@ -84,8 +79,8 @@
     /**
      * A tensor of 8 bit boolean values.
      *
-     * Values of this operand type are either true or false. A zero value represents false; any
-     * other value represents true.
+     * Values of this operand type are either true or false. A zero value
+     * represents false; any other value represents true.
      */
     TENSOR_BOOL8 = 9,
     /**
@@ -95,8 +90,9 @@
     /**
      * A tensor of 8 bit signed integers that represent real numbers.
      *
-     * This tensor is associated with additional fields that can be used to convert the 8 bit signed
-     * integer to the real value and vice versa. These fields are:
+     * This tensor is associated with additional fields that can
+     * be used to convert the 8 bit signed integer to the real value and vice versa.
+     * These fields are:
      * - channelDim: a 32 bit unsigned integer indicating channel dimension.
      * - scales: an array of positive 32 bit floating point values.
      * The size of the scales array must be equal to dimensions[channelDim].
@@ -113,8 +109,8 @@
     /**
      * A tensor of 16 bit unsigned integers that represent real numbers.
      *
-     * Attached to this tensor are two numbers that can be used to convert the 16 bit integer to the
-     * real value and vice versa. These two numbers are:
+     * Attached to this tensor are two numbers that can be used to convert the
+     * 16 bit integer to the real value and vice versa. These two numbers are:
      * - scale: a 32 bit floating point value greater than zero.
      * - zeroPoint: a 32 bit integer, in range [0, 65535].
      *
@@ -125,8 +121,8 @@
     /**
      * A tensor of 8 bit signed integers that represent real numbers.
      *
-     * Attached to this tensor is a number representing real value scale that is used to convert the
-     * 8 bit number to a real value in the following way:
+     * Attached to this tensor is a number representing real value scale that is
+     * used to convert the 8 bit number to a real value in the following way:
      * realValue = integerValue * scale.
      *
      * scale is a 32 bit floating point with value greater than zero.
@@ -135,8 +131,8 @@
     /**
      * A tensor of 8 bit signed integers that represent real numbers.
      *
-     * Attached to this tensor are two numbers that can be used to convert the 8 bit integer to the
-     * real value and vice versa. These two numbers are:
+     * Attached to this tensor are two numbers that can be used to convert the
+     * 8 bit integer to the real value and vice versa. These two numbers are:
      * - scale: a 32 bit floating point value greater than zero.
      * - zeroPoint: a 32 bit integer, in range [-128, 127].
      *
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/OperationType.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/OperationType.aidl
index 3499fc1..5f7810b 100644
--- a/neuralnetworks/aidl/android/hardware/neuralnetworks/OperationType.aidl
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/OperationType.aidl
@@ -78,6 +78,7 @@
      *      the scale and zeroPoint can be different from inputs' scale and zeroPoint.
      */
     ADD = 0,
+
     /**
      * Performs a 2-D average pooling operation.
      *
@@ -162,6 +163,7 @@
      *      the scale and zeroPoint must be the same as input0.
      */
     AVERAGE_POOL_2D = 1,
+
     /**
      * Concatenates the input tensors along the given dimension.
      *
@@ -195,11 +197,13 @@
      *      tensors. The output shape is [D0, D1, ..., sum(Daxis(i)), ..., Dm].
      *      Since HAL version 1.2, for a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
      *      the scale and zeroPoint values can be different from
-     *      input tensors. Before HAL version 1.2 they have to be the same as for the input tensors.
+     *      input tensors. Before HAL version 1.2 they have to be the same as for the
+     *      input tensors.
      *      For a {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} tensor,
      *      the scale and zeroPoint values can be different from input tensors.
      */
     CONCATENATION = 2,
+
     /**
      * Performs a 2-D convolution operation.
      *
@@ -243,7 +247,8 @@
      * * * {@link OperandType::TENSOR_INT32} for bias (with scale set to
      * * * input.scale * filter.scale).
      *
-     * * Quantized signed with filter symmetric per channel quantization (since HAL version 1.3):
+     * * Quantized signed with filter symmetric per channel quantization
+     *   (since HAL version 1.3):
      * * * {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} for input, and output.
      * * * {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} for filter.
      * * * {@link OperandType::TENSOR_INT32} for bias (scale set to 0.0,
@@ -356,10 +361,12 @@
      * Outputs:
      * * 0: The output 4-D tensor, of shape
      *      [batches, out_height, out_width, depth_out].
-     *      Before HAL version 1.2, for output tensor of {@link OperandType::TENSOR_QUANT8_ASYMM},
-     *      the following condition must be satisfied: output_scale > input_scale * filter_scale
+     *      Before HAL version 1.2, for output tensor of
+     *      {@link OperandType::TENSOR_QUANT8_ASYMM}, the following condition must
+     *      be satisfied: output_scale > input_scale * filter_scale
      */
     CONV_2D = 3,
+
     /**
      * Performs a depthwise 2-D convolution operation.
      *
@@ -407,7 +414,8 @@
      * * * {@link OperandType::TENSOR_INT32} for bias (with scale set to
      * * * input.scale * filter.scale).
      *
-     * * Quantized signed with filter symmetric per channel quantization (since HAL version 1.3):
+     * * Quantized signed with filter symmetric per channel quantization
+     *   (since HAL version 1.3):
      * * * {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} for input, and output.
      * * * {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} for filter.
      * * * {@link OperandType::TENSOR_INT32} for bias (scale set to 0.0,
@@ -521,6 +529,7 @@
      *      output_scale > input_scale * filter_scale
      */
     DEPTHWISE_CONV_2D = 4,
+
     /**
      * Rearranges data from depth into blocks of spatial data.
      *
@@ -566,6 +575,7 @@
      *      the scale and zeroPoint must be the same as input0.
      */
     DEPTH_TO_SPACE = 5,
+
     /**
      * Dequantizes the input tensor.
      *
@@ -593,6 +603,7 @@
      * * 0: A tensor with the same shape as input0.
      */
     DEQUANTIZE = 6,
+
     /**
      * Looks up sub-tensors in the input tensor.
      *
@@ -637,6 +648,7 @@
      *      the scale and zeroPoint must be the same as input1.
      */
     EMBEDDING_LOOKUP = 7,
+
     /**
      * Computes element-wise floor() on the input tensor.
      *
@@ -654,6 +666,7 @@
      *      the input tensor.
      */
     FLOOR = 8,
+
     /**
      * Denotes a fully (densely) connected layer, which connects all elements
      * in the input tensor with each element in the output tensor.
@@ -699,6 +712,7 @@
      *      condition must be satisfied: output_scale > input_scale * filter_scale.
      */
     FULLY_CONNECTED = 9,
+
     /**
      * Looks up sub-tensors in the input tensor using a key-value map.
      *
@@ -755,6 +769,7 @@
      *      A non-zero byte represents True, a hit. A zero indicates otherwise.
      */
     HASHTABLE_LOOKUP = 10,
+
     /**
      * Applies L2 normalization along the axis dimension.
      *
@@ -795,6 +810,7 @@
      *      are all zeros, the result is logical zero.
      */
     L2_NORMALIZATION = 11,
+
     /**
      * Performs an 2-D L2 pooling operation.
      *
@@ -873,6 +889,7 @@
      *      [batches, out_height, out_width, depth].
      */
     L2_POOL_2D = 12,
+
     /**
      * Applies Local Response Normalization along the depth dimension.
      *
@@ -927,6 +944,7 @@
      * * 0: The output tensor of same shape as input0.
      */
     LOCAL_RESPONSE_NORMALIZATION = 13,
+
     /**
      * Computes sigmoid activation on the input tensor element-wise.
      *
@@ -954,6 +972,7 @@
      *      the scale must be 1.f / 256 and the zeroPoint must be -128.
      */
     LOGISTIC = 14,
+
     /**
      * Projects an input to a bit vector via locality senstive hashing.
      *
@@ -967,8 +986,8 @@
      *
      * Inputs:
      * * 0: Hash functions. Dim.size == 2, DataType: Float.
-     *      Tensor[0].Dim[0]: 15 of hash functions.
-     *      Tensor[0].Dim[1]: 16 of projected output bits generated by each
+     *      Tensor[0].Dim[0]: Number of hash functions.
+     *      Tensor[0].Dim[1]: Number of projected output bits generated by each
      *      hash function.
      *      If the projection type is Sparse:
      *      Tensor[0].Dim[1] + ceil(log2(Tensor[0].Dim[0])) <= 32
@@ -1009,6 +1028,7 @@
      * The offset value for sparse projections was added in HAL version 1.2.
      */
     LSH_PROJECTION = 15,
+
     /**
      * Performs a single time step in a Long Short-Term Memory (LSTM) layer
      *
@@ -1226,6 +1246,7 @@
      *      the same as the current “output state (out)” value.
      */
     LSTM = 16,
+
     /**
      * Performs an 2-D max pooling operation.
      *
@@ -1310,6 +1331,7 @@
      *      the scale and zeroPoint must be the same as input0.
      */
     MAX_POOL_2D = 17,
+
     /**
      * Multiplies two tensors, element-wise.
      *
@@ -1356,6 +1378,7 @@
      *      output_scale > input1_scale * input2_scale.
      */
     MUL = 18,
+
     /**
      * Computes rectified linear activation on the input tensor element-wise.
      *
@@ -1382,6 +1405,7 @@
      *      the scale and zeroPoint must be the same as input0.
      */
     RELU = 19,
+
     /**
      * Computes rectified linear 1 activation on the input tensor element-wise.
      *
@@ -1408,6 +1432,7 @@
      *      the scale and zeroPoint must be the same as input0.
      */
     RELU1 = 20,
+
     /**
      * Computes rectified linear 6 activation on the input tensor element-wise.
      *
@@ -1434,6 +1459,7 @@
      *      the scale and zeroPoint must be the same as input0.
      */
     RELU6 = 21,
+
     /**
      * Reshapes a tensor.
      *
@@ -1467,6 +1493,7 @@
      *      the scale and zeroPoint must be the same as input0.
      */
     RESHAPE = 22,
+
     /**
      * Resizes images to given size using the bilinear interpretation.
      *
@@ -1548,6 +1575,7 @@
      *      the scale and zeroPoint must be the same as input0.
      */
     RESIZE_BILINEAR = 23,
+
     /**
      * A basic recurrent neural network layer.
      *
@@ -1599,6 +1627,7 @@
      *      the same as the current state value.
      */
     RNN = 24,
+
     /**
      * Computes the softmax activation on the input tensor element-wise, per
      * batch, by normalizing the input vector so the maximum coefficient is
@@ -1646,6 +1675,7 @@
      *      the scale must be 1.f / 256 and the zeroPoint must be -128.
      */
     SOFTMAX = 25,
+
     /**
      * Rearranges blocks of spatial data, into depth.
      *
@@ -1690,6 +1720,7 @@
      *      the scale and zeroPoint must be the same as input0.
      */
     SPACE_TO_DEPTH = 26,
+
     /**
      * SVDF op is a kind of stateful layer derived from the notion that a
      * densely connected layer that's processing a sequence of input frames can
@@ -1766,6 +1797,7 @@
      *      [batch_size, num_units].
      */
     SVDF = 27,
+
     /**
      * Computes hyperbolic tangent of input tensor element-wise.
      *
@@ -1793,6 +1825,7 @@
      *      the scale must be 1.f / 128 and the zeroPoint must be 0.
      */
     TANH = 28,
+
     /**
      * BatchToSpace for N-dimensional tensors.
      *
@@ -1831,6 +1864,7 @@
      *      the scale and zeroPoint must be the same as input0.
      */
     BATCH_TO_SPACE_ND = 29,
+
     /**
      * Element-wise division of two tensors.
      *
@@ -1881,6 +1915,7 @@
      * * 0: A tensor of the same {@link OperandType} as input0.
      */
     DIV = 30,
+
     /**
      * Computes the mean of elements across dimensions of a tensor.
      *
@@ -1920,6 +1955,7 @@
      *      shape is [1].
      */
     MEAN = 31,
+
     /**
      * Pads a tensor.
      *
@@ -1961,6 +1997,7 @@
      *      Since HAL version 1.2, the pad value is always the logical zero.
      */
     PAD = 32,
+
     /**
      * SpaceToBatch for N-Dimensional tensors.
      *
@@ -2013,6 +2050,7 @@
      *      Since HAL version 1.2, the pad value is always the logical zero.
      */
     SPACE_TO_BATCH_ND = 33,
+
     /**
      * Removes dimensions of size 1 from the shape of a tensor.
      *
@@ -2048,6 +2086,7 @@
      *      output shape is [1].
      */
     SQUEEZE = 34,
+
     /**
      * Extracts a strided slice of a tensor.
      *
@@ -2098,6 +2137,7 @@
      *      shape is [1].
      */
     STRIDED_SLICE = 35,
+
     /**
      * Element-wise subtraction of two tensors.
      *
@@ -2148,6 +2188,7 @@
      *      the scale and zeroPoint can be different from inputs' scale and zeroPoint.
      */
     SUB = 36,
+
     /**
      * Transposes the input tensor, permuting the dimensions according to the
      * perm tensor.
@@ -2178,6 +2219,7 @@
      *      the scale and zeroPoint must be the same as input0.
      */
     TRANSPOSE = 37,
+
     /**
      * Computes the absolute value of a tensor, element-wise.
      *
@@ -2195,6 +2237,7 @@
      * * 0: The output tensor of same shape as input0.
      */
     ABS = 38,
+
     /**
      * Returns the index of the largest element along an axis.
      *
@@ -2217,7 +2260,10 @@
      * * 0: An (n - 1)-D {@link OperandType::TENSOR_INT32} tensor.
      *      If input is 1-dimensional, the output shape is [1].
      */
+    // There is no underscore in ARG_MAX to avoid name conflict with
+    // the macro defined in libc/kernel/uapi/linux/limits.h.
     ARGMAX = 39,
+
     /**
      * Returns the index of the smallest element along an axis.
      *
@@ -2240,7 +2286,8 @@
      * * 0: An (n - 1)-D {@link OperandType::TENSOR_INT32} tensor.
      *      If input is 1-dimensional, the output shape is [1].
      */
-    ARGMIN = 40,
+    ARGMIN = 40, // See ARGMAX for naming discussion.
+
     /**
      * Transform axis-aligned bounding box proposals using bounding box deltas.
      *
@@ -2287,6 +2334,7 @@
      *      scale must be 0.125 and the zero point must be 0.
      */
     AXIS_ALIGNED_BBOX_TRANSFORM = 41,
+
     /**
      * A recurrent neural network layer that applies an LSTM cell to a
      * sequence of inputs in forward and backward directions.
@@ -2561,6 +2609,7 @@
      *      Available since HAL version 1.3.
      */
     BIDIRECTIONAL_SEQUENCE_LSTM = 42,
+
     /**
      * A recurrent neural network layer that applies a basic RNN cell to a
      * sequence of inputs in forward and backward directions.
@@ -2712,6 +2761,7 @@
      *      Available since HAL version 1.3.
      */
     BIDIRECTIONAL_SEQUENCE_RNN = 43,
+
     /**
      * Greedily selects a subset of bounding boxes in descending order of score.
      *
@@ -2795,6 +2845,7 @@
      *      with the same batch index are grouped together.
      */
     BOX_WITH_NMS_LIMIT = 44,
+
     /**
      * Casts a tensor to a type.
      *
@@ -2825,6 +2876,7 @@
      * * 0: A tensor with the same shape as input0.
      */
     CAST = 45,
+
     /**
      * Shuffle the channels of the input tensor.
      *
@@ -2864,6 +2916,7 @@
      *      the scale and zeroPoint must be the same as input0.
      */
     CHANNEL_SHUFFLE = 46,
+
     /**
      * Apply postprocessing steps to bounding box detections.
      *
@@ -2943,6 +2996,7 @@
      *      specifying the number of valid output detections for each batch.
      */
     DETECTION_POSTPROCESSING = 47,
+
     /**
      * For input tensors x and y, computes x == y elementwise.
      *
@@ -2967,6 +3021,7 @@
      * * 0: A tensor of {@link OperandType::TENSOR_BOOL8}.
      */
     EQUAL = 48,
+
     /**
      * Computes exponential of x element-wise.
      *
@@ -2983,6 +3038,7 @@
      * * 0: The output tensor of same shape as input0.
      */
     EXP = 49,
+
     /**
      * Inserts a dimension of 1 into a tensor's shape.
      *
@@ -3013,6 +3069,7 @@
      *      the scale and zeroPoint must be the same as input0.
      */
     EXPAND_DIMS = 50,
+
     /**
      * Gathers values along an axis.
      *
@@ -3052,6 +3109,7 @@
      *      the scale and zeroPoint must be the same as input0.
      */
     GATHER = 51,
+
     /**
      * Generate aixs-aligned bounding box proposals.
      *
@@ -3133,6 +3191,7 @@
      *      with the same batch index are grouped together.
      */
     GENERATE_PROPOSALS = 52,
+
     /**
      * For input tensors x and y, computes x > y elementwise.
      *
@@ -3181,6 +3240,7 @@
      * * 0: A tensor of {@link OperandType::TENSOR_BOOL8}.
      */
     GREATER_EQUAL = 54,
+
     /**
      * Performs a grouped 2-D convolution operation.
      *
@@ -3233,7 +3293,8 @@
      * * * {@link OperandType::TENSOR_INT32} for bias (scale set to 0.0,
      * * * each value scaling is separate and equal to input.scale * filter.scales[channel]).
      *
-     * * Quantized signed with filter symmetric per channel quantization (since HAL version 1.3):
+     * * Quantized signed with filter symmetric per channel quantization
+     *   (since HAL version 1.3):
      * * * {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} for input, and output.
      * * * {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} for filter.
      * * * {@link OperandType::TENSOR_INT32} for bias (scale set to 0.0,
@@ -3330,6 +3391,7 @@
      *      the scale and zeroPoint can be different from inputs' scale and zeroPoint.
      */
     GROUPED_CONV_2D = 55,
+
     /**
      * Localize the maximum keypoints from heatmaps.
      *
@@ -3383,6 +3445,7 @@
      *      scale must be 0.125 and the zero point must be 0.
      */
     HEATMAP_MAX_KEYPOINT = 56,
+
     /**
      * Applies instance normalization to the input tensor.
      *
@@ -3433,6 +3496,7 @@
      * * 0: A tensor of the same {@link OperandType} and same shape as input0.
      */
     INSTANCE_NORMALIZATION = 57,
+
     /**
      * For input tensors x and y, computes x < y elementwise.
      *
@@ -3457,6 +3521,7 @@
      * * 0: A tensor of {@link OperandType::TENSOR_BOOL8}.
      */
     LESS = 58,
+
     /**
      * For input tensors x and y, computes x <= y elementwise.
      *
@@ -3481,6 +3546,7 @@
      * * 0: A tensor of {@link OperandType::TENSOR_BOOL8}.
      */
     LESS_EQUAL = 59,
+
     /**
      * Computes natural logarithm of x element-wise.
      *
@@ -3497,6 +3563,7 @@
      * * 0: The output tensor of same shape as input0.
      */
     LOG = 60,
+
     /**
      * Returns the truth value of x AND y element-wise.
      *
@@ -3516,6 +3583,7 @@
      * * 0: A tensor of {@link OperandType::TENSOR_BOOL8}.
      */
     LOGICAL_AND = 61,
+
     /**
      * Computes the truth value of NOT x element-wise.
      *
@@ -3531,6 +3599,7 @@
      * * 0: The output tensor of same shape as input0.
      */
     LOGICAL_NOT = 62,
+
     /**
      * Returns the truth value of x OR y element-wise.
      *
@@ -3550,6 +3619,7 @@
      * * 0: A tensor of {@link OperandType::TENSOR_BOOL8}.
      */
     LOGICAL_OR = 63,
+
     /**
      * Computes the log softmax activations given logits.
      *
@@ -3580,6 +3650,7 @@
      *      input0.
      */
     LOG_SOFTMAX = 64,
+
     /**
      * Returns the element-wise maximum of two tensors.
      *
@@ -3606,6 +3677,7 @@
      *      the scale and zeroPoint can be different from inputs' scale and zeroPoint.
      */
     MAXIMUM = 65,
+
     /**
      * Returns the element-wise minimum of two tensors.
      *
@@ -3632,6 +3704,7 @@
      *      the scale and zeroPoint can be different from inputs' scale and zeroPoint.
      */
     MINIMUM = 66,
+
     /**
      * Computes numerical negative value element-wise.
      *
@@ -3649,6 +3722,7 @@
      * * 0: The output tensor of same shape as input0.
      */
     NEG = 67,
+
     /**
      * For input tensors x and y, computes x != y elementwise.
      *
@@ -3673,6 +3747,7 @@
      * * 0: A tensor of {@link OperandType::TENSOR_BOOL8}.
      */
     NOT_EQUAL = 68,
+
     /**
      * Pads a tensor with the given constant value according to the specified
      * paddings.
@@ -3717,6 +3792,7 @@
      *      the scale and zeroPoint must be the same as input0.
      */
     PAD_V2 = 69,
+
     /**
      * Computes the power of one value to another.
      *
@@ -3746,6 +3822,7 @@
      * * 0: An output tensor.
      */
     POW = 70,
+
     /**
      * Parametric Rectified Linear Unit.
      *
@@ -3786,6 +3863,7 @@
      *      the scales and zeroPoint can be different from input0 scale and zeroPoint.
      */
     PRELU = 71,
+
     /**
      * Quantizes the input tensor.
      *
@@ -3817,6 +3895,7 @@
      *      {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED}.
      */
     QUANTIZE = 72,
+
     /**
      * A version of quantized LSTM, using 16 bit quantization for internal
      * state.
@@ -3921,6 +4000,7 @@
      *      (scale = 1/128, zeroPoint = 128).
      */
     QUANTIZED_16BIT_LSTM = 73,
+
     /**
      * Draws samples from a multinomial distribution.
      *
@@ -3941,6 +4021,7 @@
      *      [batches, samples], containing the drawn samples.
      */
     RANDOM_MULTINOMIAL = 74,
+
     /**
      * Reduces a tensor by computing the "logical and" of elements along given
      * dimensions.
@@ -3967,6 +4048,7 @@
      *      shape is [1].
      */
     REDUCE_ALL = 75,
+
     /**
      * Reduces a tensor by computing the "logical or" of elements along given
      * dimensions.
@@ -3993,6 +4075,7 @@
      *      shape is [1].
      */
     REDUCE_ANY = 76,
+
     /**
      * Reduces a tensor by computing the maximum of elements along given
      * dimensions.
@@ -4025,6 +4108,7 @@
      *      the scale and zeroPoint must be the same as input0.
      */
     REDUCE_MAX = 77,
+
     /**
      * Reduces a tensor by computing the minimum of elements along given
      * dimensions.
@@ -4057,6 +4141,7 @@
      *      the scale and zeroPoint must be the same as input0.
      */
     REDUCE_MIN = 78,
+
     /**
      * Reduces a tensor by multiplying elements along given dimensions.
      *
@@ -4083,6 +4168,7 @@
      *      shape is [1].
      */
     REDUCE_PROD = 79,
+
     /**
      * Reduces a tensor by summing elements along given dimensions.
      *
@@ -4109,6 +4195,7 @@
      *      shape is [1].
      */
     REDUCE_SUM = 80,
+
     /**
      * Select and scale the feature map of each region of interest to a unified
      * output size by average pooling sampling points from bilinear interpolation.
@@ -4170,6 +4257,7 @@
      *      the scale and zeroPoint can be different from the input0 scale and zeroPoint.
      */
     ROI_ALIGN = 81,
+
     /**
      * Select and scale the feature map of each region of interest to a unified
      * output size by max-pooling.
@@ -4223,12 +4311,15 @@
      *      the scale and zeroPoint must be the same as input0.
      */
     ROI_POOLING = 82,
+
     /**
      * Computes reciprocal of square root of x element-wise.
      *
      * Supported tensor {@link OperandType}:
      * * {@link OperandType::TENSOR_FLOAT16}
      * * {@link OperandType::TENSOR_FLOAT32}
+     * * {@link OperandType::TENSOR_QUANT8_ASYMM} (since NNAPI feature level 7)
+     * * {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} (since NNAPI feature level 7)
      *
      * Supported tensor rank: from 1.
      *
@@ -4237,8 +4328,12 @@
      *
      * Outputs:
      * * 0: The output tensor of same shape as input0.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} and
+     *      {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} tensor,
+     *      the scale and zeroPoint can be different from inputs' scale and zeroPoint.
      */
     RSQRT = 83,
+
     /**
      * Using a tensor of booleans c and input tensors x and y select values
      * elementwise from both input tensors:
@@ -4271,6 +4366,7 @@
      *      the scale and zeroPoint can be different from inputs' scale and zeroPoint.
      */
     SELECT = 84,
+
     /**
      * Computes sin of x element-wise.
      *
@@ -4287,6 +4383,7 @@
      * * 0: The output tensor of same shape as input0.
      */
     SIN = 85,
+
     /**
      * Extracts a slice of specified size from the input tensor starting at a
      * specified location.
@@ -4322,6 +4419,7 @@
      *      its scale and zeroPoint has to be same as the input0 scale and zeroPoint.
      */
     SLICE = 86,
+
     /**
      * Splits a tensor along a given axis into num_splits subtensors.
      *
@@ -4348,6 +4446,7 @@
      *      the scale and zeroPoint must be the same as input0.
      */
     SPLIT = 87,
+
     /**
      * Computes square root of x element-wise.
      *
@@ -4364,6 +4463,7 @@
      * * 0: The output tensor of same shape as input0.
      */
     SQRT = 88,
+
     /**
      * Constructs a tensor by tiling a given tensor.
      *
@@ -4394,6 +4494,7 @@
      *      the scale and zeroPoint must be the same as input0.
      */
     TILE = 89,
+
     /**
      * Finds values and indices of the k largest entries for the last dimension.
      *
@@ -4424,6 +4525,7 @@
      *      containing the indices of values within the last dimension of input.
      */
     TOPK_V2 = 90,
+
     /**
      * Performs the transpose of 2-D convolution operation.
      *
@@ -4458,7 +4560,8 @@
      * * * {@link OperandType::TENSOR_INT32} for bias (with scale set to
      * * * input.scale * filter.scale).
      *
-     * * Quantized signed with filter symmetric per channel quantization (since HAL version 1.3):
+     * * Quantized signed with filter symmetric per channel quantization
+     *   (since HAL version 1.3):
      * * * {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} for input, and output.
      * * * {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} for filter.
      * * * {@link OperandType::TENSOR_INT32} for bias (scale set to 0.0,
@@ -4552,6 +4655,7 @@
      *      the scale and zeroPoint can be different from inputs' scale and zeroPoint.
      */
     TRANSPOSE_CONV_2D = 91,
+
     /**
      * A recurrent neural network specified by an LSTM cell.
      *
@@ -4669,6 +4773,7 @@
      *      Available since HAL version 1.3.
      */
     UNIDIRECTIONAL_SEQUENCE_LSTM = 92,
+
     /**
      * A recurrent neural network layer that applies a basic RNN cell to a
      * sequence of inputs.
@@ -4727,6 +4832,7 @@
      *      Available since HAL version 1.3.
      */
     UNIDIRECTIONAL_SEQUENCE_RNN = 93,
+
     /**
      * Resizes images to given size using the nearest neighbor interpretation.
      *
@@ -4805,6 +4911,7 @@
      *      the scale and zeroPoint must be the same as input0.
      */
     RESIZE_NEAREST_NEIGHBOR = 94,
+
     /**
      * Quantized version of {@link OperationType::LSTM}.
      *
@@ -4933,6 +5040,7 @@
      *      Shape: [batchSize, outputSize]
      */
     QUANTIZED_LSTM = 95,
+
     /**
      * Executes one of the two referenced subgraphs as determined by a boolean
      * value.
@@ -4959,6 +5067,7 @@
      * * 0 ~ (m - 1): Outputs produced by the selected subgraph.
      */
     IF = 96,
+
     /**
      * Executes the body subgraph until the condition subgraph outputs false.
      *
@@ -5025,6 +5134,7 @@
      * * 0 ~ (m - 1): Outputs produced by the loop.
      */
     WHILE = 97,
+
     /**
      * Computes exponential linear activation on the input tensor element-wise.
      *
@@ -5050,6 +5160,7 @@
      * * 0: The output tensor of same shape and type as input0.
      */
     ELU = 98,
+
     /**
      * Computes hard-swish activation on the input tensor element-wise.
      *
@@ -5077,6 +5188,7 @@
      *      tensor's parameters.
      */
     HARD_SWISH = 99,
+
     /**
      * Creates a tensor filled with a scalar value.
      *
@@ -5101,6 +5213,7 @@
      * * 0: The output tensor.
      */
     FILL = 100,
+
     /**
      * Returns the rank of a tensor.
      *
@@ -5214,4 +5327,85 @@
      * * 0: The packed tensor.
      */
     PACK = 103,
+
+    /**
+     * Pads a tensor with mirrored values.
+     *
+     * This operator specifies one of two padding modes: REFLECT or SYMMETRIC.
+     * In the case of REFLECT mode, the mirroring excludes the border element
+     * on the padding side.
+     * In the case of SYMMETRIC mode, the mirroring includes the border element
+     * on the padding side.
+     *
+     * For example, if the input is the 1-D tensor `[1, 2, 3]` and the padding
+     * is `[0, 2]` (i.e., pad no elements before the first (and only) dimension,
+     * and two elements after the first (and only) dimension), then:
+     *     - REFLECT mode produces the output `[1, 2, 3, 2, 1]`
+     *     - SYMMETRIC mode produces the output `[1, 2, 3, 3, 2]`
+     *
+     * Supported tensor {@link OperandType}:
+     * * {@link OperandType::TENSOR_FLOAT16}
+     * * {@link OperandType::TENSOR_FLOAT32}
+     * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * * {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED}
+     * * {@link OperandType::TENSOR_INT32}
+     *
+     * Supported tensor rank: from 1.
+     *
+     * Inputs:
+     * * 0: An n-D tensor, specifying the tensor to be padded.
+     * * 1: A 2-D tensor of {@link OperandType::TENSOR_INT32}, the paddings
+     *      for each spatial dimension of the input tensor. The shape of the
+     *      tensor must be {rank(input0), 2}.
+     *      padding[i, 0] specifies the number of elements to be padded in the
+     *      front of dimension i.
+     *      padding[i, 1] specifies the number of elements to be padded after the
+     *      end of dimension i.
+     *      Each padding value must be nonnegative.
+     *      In the case of REFLECT mode, each padding value must be less than the
+     *      corresponding dimension.
+     *      In the case of SYMMETRIC mode, each padding value must be less than or
+     *      equal to the corresponding dimension.
+     * * 2: An {@link OperandType::INT32} scalar, specifying the mode.
+     *      Options are 0:REFLECT and 1:SYMMETRIC.
+     *
+     * Outputs:
+     * * 0: A tensor of the same {@link OperandType} as input0. The
+     *      output tensor has the same rank as input0, and each
+     *      dimension of the output tensor has the same size as the
+     *      corresponding dimension of the input tensor plus the size
+     *      of the padding:
+     *          output0.dimension[i] =
+     *              padding[i, 0] + input0.dimension[i] + padding[i, 1]
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} and
+     *      {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} tensor,
+     *      the scale and zeroPoint must be the same as input0.
+     */
+    MIRROR_PAD = 104,
+
+    /**
+     * Reverses a specified dimension of a tensor.
+     *
+     * Supported tensor {@link OperandType}:
+     * * {@link OperandType::TENSOR_FLOAT16}
+     * * {@link OperandType::TENSOR_FLOAT32}
+     * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * * {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED}
+     * * {@link OperandType::TENSOR_INT32}
+     *
+     * Supported tensor rank: up to 8.
+     *
+     * Inputs:
+     * * 0: Input tensor of rank n.
+     * * 1: Axis tensor of type {@link OperandType::TENSOR_INT32} and shape [1],
+     *      specifying which dimension of the input tensor is to be reversed. The dimension
+     *      must be in the range [0, n).
+     *
+     * Outputs:
+     * * 0: The reversed tensor of the same shape as the input tensor.
+     *      For {@link OperandType::TENSOR_QUANT8_ASYMM} and
+     *      {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} tensors,
+     *      the scales and zeroPoint must be the same as input0.
+     */
+    REVERSE = 105,
 }
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/PrepareModelConfig.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/PrepareModelConfig.aidl
new file mode 100644
index 0000000..55bd291
--- /dev/null
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/PrepareModelConfig.aidl
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.neuralnetworks;
+
+import android.hardware.neuralnetworks.ExecutionPreference;
+import android.hardware.neuralnetworks.ExtensionNameAndPrefix;
+import android.hardware.neuralnetworks.Priority;
+import android.hardware.neuralnetworks.TokenValuePair;
+
+/**
+ * A type that is used to represent all configuration needed to
+ * prepare a model.
+ */
+@VintfStability
+parcelable PrepareModelConfig {
+    /**
+     * The byte size of the cache token.
+     */
+    const int BYTE_SIZE_OF_CACHE_TOKEN = 32;
+
+    /**
+     * Indicates the intended execution behavior of a prepared model.
+     */
+    ExecutionPreference preference;
+    /**
+     * The priority of the prepared model relative to other prepared
+     * models owned by the client.
+     */
+    Priority priority;
+    /**
+     * The time by which the model is expected to be prepared. The
+     * time is measured in nanoseconds since boot (as from
+     * clock_gettime(CLOCK_BOOTTIME, &ts) or
+     * ::android::base::boot_clock). If the model cannot be prepared
+     * by the deadline, the preparation may be aborted. Passing -1
+     * means the deadline is omitted. Other negative values are
+     * invalid.
+     */
+    long deadlineNs;
+    /**
+     * A vector of file descriptors for the security-sensitive cache.
+     * The length of the vector must either be 0 indicating that
+     * caching information is not provided, or match the
+     * numModelCache returned from IDevice::getNumberOfCacheFilesNeeded. The
+     * cache file descriptors will be provided in the same order when
+     * retrieving the preparedModel from cache files with
+     * IDevice::prepareModelFromCache.
+     */
+    ParcelFileDescriptor[] modelCache;
+    /**
+     * A vector of file descriptors for the constants' cache. The
+     * length of the vector must either be 0 indicating that caching
+     * information is not provided, or match the numDataCache
+     * returned from IDevice::getNumberOfCacheFilesNeeded. The cache file
+     * descriptors will be provided in the same order when retrieving
+     * the preparedModel from cache files with IDevice::prepareModelFromCache.
+     */
+    ParcelFileDescriptor[] dataCache;
+    /**
+     * A caching token of length BYTE_SIZE_OF_CACHE_TOKEN identifying
+     * the prepared model. The same token will be provided when
+     * retrieving the prepared model from the cache files with
+     * IDevice::prepareModelFromCache.  Tokens should be chosen to have a low
+     * rate of collision for a particular application. The driver
+     * cannot detect a collision; a collision will result in a failed
+     * execution or in a successful execution that produces incorrect
+     * output values. If both modelCache and dataCache are empty
+     * indicating that caching information is not provided, this
+     * token must be ignored.
+     */
+    byte[BYTE_SIZE_OF_CACHE_TOKEN] cacheToken;
+    /**
+     * A vector of token / value pairs represent vendor specific
+     * compilation hints or metadata. The provided TokenValuePairs must not
+     * contain the same token twice. The driver must validate the
+     * data and ignore invalid hints. It is up to the driver to
+     * decide whether to respect the provided hints or not.
+     */
+    TokenValuePair[] compilationHints;
+    /**
+     * The mapping between extension names and prefixes of token values.
+     * The driver must ignore the corresponding compilation hint, if
+     * the extension is not supported.
+     */
+    ExtensionNameAndPrefix[] extensionNameToPrefix;
+}
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/TokenValuePair.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/TokenValuePair.aidl
new file mode 100644
index 0000000..ec665b4
--- /dev/null
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/TokenValuePair.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.neuralnetworks;
+
+/**
+ * A type that is used to represent a token / byte array data pair.
+ */
+@VintfStability
+parcelable TokenValuePair {
+    /**
+     * A 32bit integer token. The token is created by combining the
+     * extension prefix and enum defined within the extension.
+     * The low {@link IDevice::EXTENSION_TYPE_LOW_BITS_TYPE} bits of the value
+     * correspond to the hint within the extension and the high
+     * {@link IDevice::EXTENSION_TYPE_HIGH_BITS_PREFIX} bits encode the "prefix", which maps
+     * uniquely to the extension name. The sign bit is always 0.
+     *
+     * For example, if a token value is 0x7AAA000B and the corresponding
+     * {@link ExtensionNameAndPrefix} contains an entry with prefix=0x7AAA and
+     * name="vendor.test.test_extension", then the token should be interpreted as the hint
+     * 0x000B of the extension named vendor.test.test_extension.
+     */
+    int token;
+    /**
+     * A byte array containing the raw data.
+     */
+    byte[] value;
+}
diff --git a/neuralnetworks/aidl/utils/Android.bp b/neuralnetworks/aidl/utils/Android.bp
index 1615c46..2b7b787 100644
--- a/neuralnetworks/aidl/utils/Android.bp
+++ b/neuralnetworks/aidl/utils/Android.bp
@@ -23,56 +23,111 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
-cc_library_static {
-    name: "neuralnetworks_utils_hal_aidl",
+cc_defaults {
+    name: "neuralnetworks_utils_hal_aidl_defaults",
     defaults: ["neuralnetworks_utils_defaults"],
-    srcs: ["src/*"],
+    srcs: [
+        // AIDL utils that a driver may depend on.
+        "src/BufferTracker.cpp",
+        "src/Conversions.cpp",
+        "src/HalUtils.cpp",
+        "src/Utils.cpp",
+        "src/ValidateHal.cpp",
+    ],
     local_include_dirs: ["include/nnapi/hal/aidl/"],
     export_include_dirs: ["include"],
     cflags: ["-Wthread-safety"],
     static_libs: [
-        "android.hardware.graphics.common-V2-ndk_platform",
+        "android.hardware.graphics.common-V2-ndk",
         "libaidlcommonsupport",
         "libarect",
         "neuralnetworks_types",
         "neuralnetworks_utils_hal_common",
     ],
     shared_libs: [
-        "android.hardware.neuralnetworks-V2-ndk_platform",
         "libbinder_ndk",
-        "libhidlbase",
-        "libnativewindow",
     ],
+    target: {
+        android: {
+            shared_libs: ["libnativewindow"],
+        },
+    },
+}
+
+// Deprecated. Remove once all modules depending on this are migrated away.
+cc_library_static {
+    name: "neuralnetworks_utils_hal_aidl_v1",
+    defaults: ["neuralnetworks_utils_hal_aidl_defaults"],
+    shared_libs: [
+        "android.hardware.neuralnetworks-V1-ndk",
+    ],
+}
+
+cc_library_static {
+    name: "neuralnetworks_utils_hal_aidl",
+    defaults: ["neuralnetworks_utils_hal_aidl_defaults"],
+    srcs: [
+        // Additional AIDL utils for the runtime.
+        "src/Assertions.cpp",
+        "src/Buffer.cpp",
+        "src/Burst.cpp",
+        "src/Callbacks.cpp",
+        "src/Device.cpp",
+        "src/Execution.cpp",
+        "src/InvalidDevice.cpp",
+        "src/PreparedModel.cpp",
+        "src/ProtectCallback.cpp",
+        "src/Service.cpp",
+    ],
+    shared_libs: [
+        "android.hardware.neuralnetworks-V4-ndk",
+    ],
+    cflags: ["-DNN_AIDL_V4_OR_ABOVE"],
+}
+
+// A cc_defaults that includes the latest non-experimental AIDL utilities and other AIDL libraries
+// that are commonly used together. Modules that always depend on the latest non-experimental
+// AIDL features can include this cc_defaults to avoid managing dependency versions explicitly.
+cc_defaults {
+    name: "neuralnetworks_use_latest_utils_hal_aidl",
+    static_libs: [
+        "android.hardware.common-V2-ndk",
+        "android.hardware.graphics.common-V2-ndk",
+        "android.hardware.neuralnetworks-V4-ndk",
+        "neuralnetworks_utils_hal_aidl",
+    ],
+    cflags: ["-DNN_AIDL_V4_OR_ABOVE"],
 }
 
 cc_test {
     name: "neuralnetworks_utils_hal_aidl_test",
-    defaults: ["neuralnetworks_utils_defaults"],
+    defaults: [
+        "neuralnetworks_use_latest_utils_hal_aidl",
+        "neuralnetworks_utils_defaults",
+    ],
+    tidy_timeout_srcs: [
+        "test/DeviceTest.cpp",
+        "test/PreparedModelTest.cpp",
+    ],
     srcs: [
         "test/*.cpp",
     ],
     static_libs: [
-        "android.hardware.common-V2-ndk_platform",
-        "android.hardware.graphics.common-V2-ndk_platform",
-        "android.hardware.neuralnetworks-V2-ndk_platform",
         "libaidlcommonsupport",
         "libgmock",
-        "libneuralnetworks_common",
         "neuralnetworks_types",
-        "neuralnetworks_utils_hal_aidl",
         "neuralnetworks_utils_hal_common",
     ],
     shared_libs: [
-        "android.hidl.allocator@1.0",
         "libbase",
         "libbinder_ndk",
         "libcutils",
-        "libhidlbase",
-        "libhidlmemory",
-        "liblog",
-        "libnativewindow",
-        "libutils",
     ],
+    target: {
+        android: {
+            shared_libs: ["libnativewindow"],
+        },
+    },
     cflags: [
         /* GMOCK defines functions for printing all MOCK_DEVICE arguments and
          * MockDevice contains a string pointer which triggers a warning in the
diff --git a/neuralnetworks/aidl/utils/OWNERS b/neuralnetworks/aidl/utils/OWNERS
deleted file mode 100644
index e4feee3..0000000
--- a/neuralnetworks/aidl/utils/OWNERS
+++ /dev/null
@@ -1,11 +0,0 @@
-# Neuralnetworks team
-butlermichael@google.com
-dgross@google.com
-galarragas@google.com
-jeanluc@google.com
-levp@google.com
-miaowang@google.com
-pszczepaniak@google.com
-slavash@google.com
-vddang@google.com
-xusongw@google.com
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/BufferTracker.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/BufferTracker.h
new file mode 100644
index 0000000..18d01e2
--- /dev/null
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/BufferTracker.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_BUFFER_TRACKER_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_BUFFER_TRACKER_H
+
+#include <android-base/macros.h>
+#include <android-base/thread_annotations.h>
+
+#include <map>
+#include <memory>
+#include <mutex>
+#include <set>
+#include <stack>
+#include <utility>
+#include <vector>
+
+#include "nnapi/hal/aidl/HalInterfaces.h"
+#include "nnapi/hal/aidl/ValidateHal.h"
+
+namespace android::nn {
+
+// This class manages a CPU buffer allocated on heap and provides validation methods.
+class AidlManagedBuffer {
+  public:
+    static std::shared_ptr<AidlManagedBuffer> create(uint32_t size,
+                                                     std::set<AidlHalPreparedModelRole> roles,
+                                                     const Operand& operand);
+
+    // Prefer AidlManagedBuffer::create.
+    AidlManagedBuffer(std::unique_ptr<uint8_t[]> buffer, uint32_t size,
+                      std::set<AidlHalPreparedModelRole> roles, const Operand& operand);
+
+    uint8_t* getPointer() const { return kBuffer.get(); }
+    uint32_t getSize() const { return kSize; }
+
+    // "poolIndex" is the index of this buffer in the request.pools.
+    ErrorStatus validateRequest(uint32_t poolIndex, const Request& request,
+                                const aidl_hal::IPreparedModel* preparedModel) const;
+
+    // "size" is the byte size of the Memory provided to the copyFrom or copyTo method.
+    ErrorStatus validateCopyFrom(const std::vector<uint32_t>& dimensions, uint32_t size) const;
+    ErrorStatus validateCopyTo(uint32_t size) const;
+
+    bool updateDimensions(const std::vector<uint32_t>& dimensions);
+    void setInitialized(bool initialized);
+
+  private:
+    mutable std::mutex mMutex;
+    const std::unique_ptr<uint8_t[]> kBuffer;
+    const uint32_t kSize;
+    const std::set<AidlHalPreparedModelRole> kRoles;
+    const OperandType kOperandType;
+    const std::vector<uint32_t> kInitialDimensions;
+    std::vector<uint32_t> mUpdatedDimensions GUARDED_BY(mMutex);
+    bool mInitialized GUARDED_BY(mMutex) = false;
+};
+
+// Keep track of all AidlManagedBuffers and assign each with a unique token.
+class AidlBufferTracker : public std::enable_shared_from_this<AidlBufferTracker> {
+    DISALLOW_COPY_AND_ASSIGN(AidlBufferTracker);
+
+  public:
+    // A RAII class to help manage the lifetime of the token.
+    // It is only supposed to be constructed in AidlBufferTracker::add.
+    class Token {
+        DISALLOW_COPY_AND_ASSIGN(Token);
+
+      public:
+        Token(uint32_t token, std::shared_ptr<AidlBufferTracker> tracker)
+            : kToken(token), kBufferTracker(std::move(tracker)) {}
+        ~Token() { kBufferTracker->free(kToken); }
+        uint32_t get() const { return kToken; }
+
+      private:
+        const uint32_t kToken;
+        const std::shared_ptr<AidlBufferTracker> kBufferTracker;
+    };
+
+    // The factory of AidlBufferTracker. This ensures that the AidlBufferTracker is always managed
+    // by a shared_ptr.
+    static std::shared_ptr<AidlBufferTracker> create() {
+        return std::make_shared<AidlBufferTracker>();
+    }
+
+    // Prefer AidlBufferTracker::create.
+    AidlBufferTracker() : mTokenToBuffers(1) {}
+
+    std::unique_ptr<Token> add(std::shared_ptr<AidlManagedBuffer> buffer);
+    std::shared_ptr<AidlManagedBuffer> get(uint32_t token) const;
+
+  private:
+    void free(uint32_t token);
+
+    mutable std::mutex mMutex;
+    std::stack<uint32_t, std::vector<uint32_t>> mFreeTokens GUARDED_BY(mMutex);
+
+    // Since the tokens are allocated in a non-sparse way, we use a vector to represent the mapping.
+    // The index of the vector is the token. When the token gets freed, the corresponding entry is
+    // set to nullptr. mTokenToBuffers[0] is always set to nullptr because 0 is an invalid token.
+    std::vector<std::shared_ptr<AidlManagedBuffer>> mTokenToBuffers GUARDED_BY(mMutex);
+};
+
+}  // namespace android::nn
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_BUFFER_TRACKER_H
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Burst.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Burst.h
index 0cc78d4..f2e6e75 100644
--- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Burst.h
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Burst.h
@@ -86,10 +86,12 @@
                 GUARDED_BY(mMutex);
     };
 
+    // featureLevel is for testing purposes.
     static nn::GeneralResult<std::shared_ptr<const Burst>> create(
-            std::shared_ptr<aidl_hal::IBurst> burst);
+            std::shared_ptr<aidl_hal::IBurst> burst, nn::Version featureLevel);
 
-    Burst(PrivateConstructorTag tag, std::shared_ptr<aidl_hal::IBurst> burst);
+    Burst(PrivateConstructorTag tag, std::shared_ptr<aidl_hal::IBurst> burst,
+          nn::Version featureLevel);
 
     // See IBurst::cacheMemory for information.
     OptionalCacheHold cacheMemory(const nn::SharedMemory& memory) const override;
@@ -97,23 +99,29 @@
     // See IBurst::execute for information.
     nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
             const nn::Request& request, nn::MeasureTiming measure,
-            const nn::OptionalTimePoint& deadline,
-            const nn::OptionalDuration& loopTimeoutDuration) const override;
+            const nn::OptionalTimePoint& deadline, const nn::OptionalDuration& loopTimeoutDuration,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
 
     // See IBurst::createReusableExecution for information.
     nn::GeneralResult<nn::SharedExecution> createReusableExecution(
             const nn::Request& request, nn::MeasureTiming measure,
-            const nn::OptionalDuration& loopTimeoutDuration) const override;
+            const nn::OptionalDuration& loopTimeoutDuration,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
 
     nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> executeInternal(
             const aidl_hal::Request& request, const std::vector<int64_t>& memoryIdentifierTokens,
             bool measure, int64_t deadline, int64_t loopTimeoutDuration,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix,
             const hal::utils::RequestRelocation& relocation) const;
 
   private:
     mutable std::atomic_flag mExecutionInFlight = ATOMIC_FLAG_INIT;
     const std::shared_ptr<aidl_hal::IBurst> kBurst;
     const std::shared_ptr<MemoryCache> kMemoryCache;
+    const nn::Version kFeatureLevel;
 };
 
 }  // namespace aidl::android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Callbacks.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Callbacks.h
index 8651912..960be2b 100644
--- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Callbacks.h
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Callbacks.h
@@ -32,11 +32,12 @@
 namespace aidl::android::hardware::neuralnetworks::utils {
 
 // An AIDL callback class to receive the results of IDevice::prepareModel* asynchronously.
-class PreparedModelCallback final : public BnPreparedModelCallback,
-                                    public hal::utils::IProtectedCallback {
+class PreparedModelCallback final : public BnPreparedModelCallback, public IProtectedCallback {
   public:
     using Data = nn::GeneralResult<nn::SharedPreparedModel>;
 
+    PreparedModelCallback(nn::Version featureLevel) : kFeatureLevel(featureLevel) {}
+
     ndk::ScopedAStatus notify(ErrorStatus status,
                               const std::shared_ptr<IPreparedModel>& preparedModel) override;
 
@@ -45,6 +46,7 @@
     Data get();
 
   private:
+    const nn::Version kFeatureLevel;
     hal::utils::TransferValue<Data> mData;
 };
 
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Conversions.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Conversions.h
index 5eab9ff..71a28ef 100644
--- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Conversions.h
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Conversions.h
@@ -27,6 +27,7 @@
 #include <aidl/android/hardware/neuralnetworks/Extension.h>
 #include <aidl/android/hardware/neuralnetworks/ExtensionNameAndPrefix.h>
 #include <aidl/android/hardware/neuralnetworks/ExtensionOperandTypeInformation.h>
+#include <aidl/android/hardware/neuralnetworks/IDevice.h>
 #include <aidl/android/hardware/neuralnetworks/Memory.h>
 #include <aidl/android/hardware/neuralnetworks/Model.h>
 #include <aidl/android/hardware/neuralnetworks/Operand.h>
@@ -46,6 +47,10 @@
 #include <aidl/android/hardware/neuralnetworks/SymmPerChannelQuantParams.h>
 #include <aidl/android/hardware/neuralnetworks/Timing.h>
 
+#ifdef NN_AIDL_V4_OR_ABOVE
+#include <aidl/android/hardware/neuralnetworks/TokenValuePair.h>
+#endif  // NN_AIDL_V4_OR_ABOVE
+
 #include <android/binder_auto_utils.h>
 #include <nnapi/Result.h>
 #include <nnapi/Types.h>
@@ -74,7 +79,7 @@
         const aidl_hal::SymmPerChannelQuantParams& symmPerChannelQuantParams);
 GeneralResult<Operation> unvalidatedConvert(const aidl_hal::Operation& operation);
 GeneralResult<Model> unvalidatedConvert(const aidl_hal::Model& model);
-GeneralResult<Model::ExtensionNameAndPrefix> unvalidatedConvert(
+GeneralResult<ExtensionNameAndPrefix> unvalidatedConvert(
         const aidl_hal::ExtensionNameAndPrefix& extensionNameAndPrefix);
 GeneralResult<Model::OperandValues> unvalidatedConvert(const std::vector<uint8_t>& operandValues);
 GeneralResult<Model::Subgraph> unvalidatedConvert(const aidl_hal::Subgraph& subgraph);
@@ -95,9 +100,11 @@
 GeneralResult<Extension> unvalidatedConvert(const aidl_hal::Extension& extension);
 GeneralResult<Extension::OperandTypeInformation> unvalidatedConvert(
         const aidl_hal::ExtensionOperandTypeInformation& operandTypeInformation);
-GeneralResult<SharedHandle> unvalidatedConvert(
-        const ::aidl::android::hardware::common::NativeHandle& handle);
-GeneralResult<SyncFence> unvalidatedConvert(const ndk::ScopedFileDescriptor& syncFence);
+GeneralResult<SharedHandle> unvalidatedConvert(const ndk::ScopedFileDescriptor& handle);
+
+#ifdef NN_AIDL_V4_OR_ABOVE
+GeneralResult<TokenValuePair> unvalidatedConvert(const aidl_hal::TokenValuePair& tokenValuePair);
+#endif  // NN_AIDL_V4_OR_ABOVE
 
 GeneralResult<std::vector<Operation>> unvalidatedConvert(
         const std::vector<aidl_hal::Operation>& operations);
@@ -113,12 +120,24 @@
 GeneralResult<Priority> convert(const aidl_hal::Priority& priority);
 GeneralResult<Request> convert(const aidl_hal::Request& request);
 GeneralResult<Timing> convert(const aidl_hal::Timing& timing);
-GeneralResult<SyncFence> convert(const ndk::ScopedFileDescriptor& syncFence);
+GeneralResult<SharedHandle> convert(const ndk::ScopedFileDescriptor& handle);
+GeneralResult<BufferDesc> convert(const aidl_hal::BufferDesc& bufferDesc);
 
 GeneralResult<std::vector<Extension>> convert(const std::vector<aidl_hal::Extension>& extension);
 GeneralResult<std::vector<SharedMemory>> convert(const std::vector<aidl_hal::Memory>& memories);
+GeneralResult<std::vector<ExtensionNameAndPrefix>> convert(
+        const std::vector<aidl_hal::ExtensionNameAndPrefix>& extensionNameAndPrefix);
+
+#ifdef NN_AIDL_V4_OR_ABOVE
+GeneralResult<std::vector<TokenValuePair>> convert(
+        const std::vector<aidl_hal::TokenValuePair>& metaData);
+#endif  // NN_AIDL_V4_OR_ABOVE
+
 GeneralResult<std::vector<OutputShape>> convert(
         const std::vector<aidl_hal::OutputShape>& outputShapes);
+GeneralResult<std::vector<SharedHandle>> convert(
+        const std::vector<ndk::ScopedFileDescriptor>& handles);
+GeneralResult<std::vector<BufferRole>> convert(const std::vector<aidl_hal::BufferRole>& roles);
 
 GeneralResult<std::vector<uint32_t>> toUnsigned(const std::vector<int32_t>& vec);
 
@@ -131,6 +150,7 @@
 nn::GeneralResult<std::vector<uint8_t>> unvalidatedConvert(const nn::CacheToken& cacheToken);
 nn::GeneralResult<BufferDesc> unvalidatedConvert(const nn::BufferDesc& bufferDesc);
 nn::GeneralResult<BufferRole> unvalidatedConvert(const nn::BufferRole& bufferRole);
+nn::GeneralResult<DeviceType> unvalidatedConvert(const nn::DeviceType& deviceType);
 nn::GeneralResult<bool> unvalidatedConvert(const nn::MeasureTiming& measureTiming);
 nn::GeneralResult<Memory> unvalidatedConvert(const nn::SharedMemory& memory);
 nn::GeneralResult<OutputShape> unvalidatedConvert(const nn::OutputShape& outputShape);
@@ -149,23 +169,27 @@
 nn::GeneralResult<std::vector<uint8_t>> unvalidatedConvert(
         const nn::Model::OperandValues& operandValues);
 nn::GeneralResult<ExtensionNameAndPrefix> unvalidatedConvert(
-        const nn::Model::ExtensionNameAndPrefix& extensionNameToPrefix);
+        const nn::ExtensionNameAndPrefix& extensionNameToPrefix);
 nn::GeneralResult<Model> unvalidatedConvert(const nn::Model& model);
 nn::GeneralResult<Priority> unvalidatedConvert(const nn::Priority& priority);
 nn::GeneralResult<Request> unvalidatedConvert(const nn::Request& request);
 nn::GeneralResult<RequestArgument> unvalidatedConvert(const nn::Request::Argument& requestArgument);
 nn::GeneralResult<RequestMemoryPool> unvalidatedConvert(const nn::Request::MemoryPool& memoryPool);
 nn::GeneralResult<Timing> unvalidatedConvert(const nn::Timing& timing);
-nn::GeneralResult<int64_t> unvalidatedConvert(const nn::Duration& duration);
 nn::GeneralResult<int64_t> unvalidatedConvert(const nn::OptionalDuration& optionalDuration);
 nn::GeneralResult<int64_t> unvalidatedConvert(const nn::OptionalTimePoint& optionalTimePoint);
 nn::GeneralResult<ndk::ScopedFileDescriptor> unvalidatedConvert(const nn::SyncFence& syncFence);
-nn::GeneralResult<common::NativeHandle> unvalidatedConvert(const nn::SharedHandle& sharedHandle);
-nn::GeneralResult<ndk::ScopedFileDescriptor> unvalidatedConvertCache(
-        const nn::SharedHandle& handle);
+nn::GeneralResult<ndk::ScopedFileDescriptor> unvalidatedConvert(const nn::SharedHandle& handle);
+nn::GeneralResult<Capabilities> unvalidatedConvert(const nn::Capabilities& capabilities);
+nn::GeneralResult<Extension> unvalidatedConvert(const nn::Extension& extension);
+
+#ifdef NN_AIDL_V4_OR_ABOVE
+nn::GeneralResult<TokenValuePair> unvalidatedConvert(const nn::TokenValuePair& tokenValuePair);
+#endif  // NN_AIDL_V4_OR_ABOVE
 
 nn::GeneralResult<std::vector<uint8_t>> convert(const nn::CacheToken& cacheToken);
 nn::GeneralResult<BufferDesc> convert(const nn::BufferDesc& bufferDesc);
+nn::GeneralResult<DeviceType> convert(const nn::DeviceType& deviceType);
 nn::GeneralResult<bool> convert(const nn::MeasureTiming& measureTiming);
 nn::GeneralResult<Memory> convert(const nn::SharedMemory& memory);
 nn::GeneralResult<ErrorStatus> convert(const nn::ErrorStatus& errorStatus);
@@ -176,6 +200,8 @@
 nn::GeneralResult<Timing> convert(const nn::Timing& timing);
 nn::GeneralResult<int64_t> convert(const nn::OptionalDuration& optionalDuration);
 nn::GeneralResult<int64_t> convert(const nn::OptionalTimePoint& optionalTimePoint);
+nn::GeneralResult<Capabilities> convert(const nn::Capabilities& capabilities);
+nn::GeneralResult<Extension> convert(const nn::Extension& extension);
 
 nn::GeneralResult<std::vector<BufferRole>> convert(const std::vector<nn::BufferRole>& bufferRoles);
 nn::GeneralResult<std::vector<OutputShape>> convert(
@@ -184,8 +210,17 @@
         const std::vector<nn::SharedHandle>& handles);
 nn::GeneralResult<std::vector<ndk::ScopedFileDescriptor>> convert(
         const std::vector<nn::SyncFence>& syncFences);
+nn::GeneralResult<std::vector<Extension>> convert(const std::vector<nn::Extension>& extensions);
+nn::GeneralResult<std::vector<ExtensionNameAndPrefix>> convert(
+        const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix);
+
+#ifdef NN_AIDL_V4_OR_ABOVE
+nn::GeneralResult<std::vector<TokenValuePair>> convert(
+        const std::vector<nn::TokenValuePair>& metaData);
+#endif  // NN_AIDL_V4_OR_ABOVE
 
 nn::GeneralResult<std::vector<int32_t>> toSigned(const std::vector<uint32_t>& vec);
+std::vector<uint8_t> toVec(const std::array<uint8_t, IDevice::BYTE_SIZE_OF_CACHE_TOKEN>& token);
 
 }  // namespace aidl::android::hardware::neuralnetworks::utils
 
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Device.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Device.h
index 1457646..615c6de 100644
--- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Device.h
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Device.h
@@ -42,12 +42,14 @@
     struct PrivateConstructorTag {};
 
   public:
+    // featureLevel is for testing purposes.
     static nn::GeneralResult<std::shared_ptr<const Device>> create(
-            std::string name, std::shared_ptr<aidl_hal::IDevice> device);
+            std::string name, std::shared_ptr<aidl_hal::IDevice> device, nn::Version featureLevel);
 
     Device(PrivateConstructorTag tag, std::string name, std::string versionString,
-           nn::DeviceType deviceType, std::vector<nn::Extension> extensions,
-           nn::Capabilities capabilities, std::pair<uint32_t, uint32_t> numberOfCacheFilesNeeded,
+           nn::Version featureLevel, nn::DeviceType deviceType,
+           std::vector<nn::Extension> extensions, nn::Capabilities capabilities,
+           std::pair<uint32_t, uint32_t> numberOfCacheFilesNeeded,
            std::shared_ptr<aidl_hal::IDevice> device, DeathHandler deathHandler);
 
     const std::string& getName() const override;
@@ -66,8 +68,9 @@
     nn::GeneralResult<nn::SharedPreparedModel> prepareModel(
             const nn::Model& model, nn::ExecutionPreference preference, nn::Priority priority,
             nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
-            const std::vector<nn::SharedHandle>& dataCache,
-            const nn::CacheToken& token) const override;
+            const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
 
     nn::GeneralResult<nn::SharedPreparedModel> prepareModelFromCache(
             nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
@@ -84,6 +87,7 @@
   private:
     const std::string kName;
     const std::string kVersionString;
+    const nn::Version kFeatureLevel;
     const nn::DeviceType kDeviceType;
     const std::vector<nn::Extension> kExtensions;
     const nn::Capabilities kCapabilities;
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Execution.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Execution.h
index a77ea98..14802b9 100644
--- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Execution.h
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Execution.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_EXECUTION_H
 #define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_EXECUTION_H
 
+#include <aidl/android/hardware/neuralnetworks/IExecution.h>
+
 #include <nnapi/IExecution.h>
 #include <nnapi/Result.h>
 #include <nnapi/Types.h>
@@ -33,17 +35,22 @@
 
 namespace aidl::android::hardware::neuralnetworks::utils {
 
-class Execution final : public nn::IExecution, public std::enable_shared_from_this<Execution> {
+// A reusable execution implementation with a cached Request, internally it is still passing the
+// request to the driver in every computation.
+class ExecutionWithCachedRequest final
+    : public nn::IExecution,
+      public std::enable_shared_from_this<ExecutionWithCachedRequest> {
     struct PrivateConstructorTag {};
 
   public:
-    static nn::GeneralResult<std::shared_ptr<const Execution>> create(
+    static nn::GeneralResult<std::shared_ptr<const ExecutionWithCachedRequest>> create(
             std::shared_ptr<const PreparedModel> preparedModel, Request request,
             hal::utils::RequestRelocation relocation, bool measure, int64_t loopTimeoutDuration);
 
-    Execution(PrivateConstructorTag tag, std::shared_ptr<const PreparedModel> preparedModel,
-              Request request, hal::utils::RequestRelocation relocation, bool measure,
-              int64_t loopTimeoutDuration);
+    ExecutionWithCachedRequest(PrivateConstructorTag tag,
+                               std::shared_ptr<const PreparedModel> preparedModel, Request request,
+                               hal::utils::RequestRelocation relocation, bool measure,
+                               int64_t loopTimeoutDuration);
 
     nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> compute(
             const nn::OptionalTimePoint& deadline) const override;
@@ -60,6 +67,30 @@
     const int64_t kLoopTimeoutDuration;
 };
 
+// A reusable execution implementation that is backed by an actual AIDL IExecution object.
+class Execution final : public nn::IExecution, public std::enable_shared_from_this<Execution> {
+    struct PrivateConstructorTag {};
+
+  public:
+    static nn::GeneralResult<std::shared_ptr<const Execution>> create(
+            std::shared_ptr<aidl_hal::IExecution> execution,
+            hal::utils::RequestRelocation relocation);
+
+    Execution(PrivateConstructorTag tag, std::shared_ptr<aidl_hal::IExecution> execution,
+              hal::utils::RequestRelocation relocation);
+
+    nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> compute(
+            const nn::OptionalTimePoint& deadline) const override;
+
+    nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>> computeFenced(
+            const std::vector<nn::SyncFence>& waitFor, const nn::OptionalTimePoint& deadline,
+            const nn::OptionalDuration& timeoutDurationAfterFence) const override;
+
+  private:
+    const std::shared_ptr<aidl_hal::IExecution> kExecution;
+    const hal::utils::RequestRelocation kRelocation;
+};
+
 }  // namespace aidl::android::hardware::neuralnetworks::utils
 
 #endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_EXECUTION_H
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/HalInterfaces.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/HalInterfaces.h
new file mode 100644
index 0000000..cacdc26
--- /dev/null
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/HalInterfaces.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_HAL_INTERFACES_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_HAL_INTERFACES_H
+
+#include <aidl/android/hardware/neuralnetworks/BnBuffer.h>
+#include <aidl/android/hardware/neuralnetworks/BnBurst.h>
+#include <aidl/android/hardware/neuralnetworks/BnDevice.h>
+#include <aidl/android/hardware/neuralnetworks/BnFencedExecutionCallback.h>
+#include <aidl/android/hardware/neuralnetworks/BnPreparedModel.h>
+#include <aidl/android/hardware/neuralnetworks/BnPreparedModelCallback.h>
+#include <aidl/android/hardware/neuralnetworks/BufferDesc.h>
+#include <aidl/android/hardware/neuralnetworks/BufferRole.h>
+#include <aidl/android/hardware/neuralnetworks/Capabilities.h>
+#include <aidl/android/hardware/neuralnetworks/DataLocation.h>
+#include <aidl/android/hardware/neuralnetworks/DeviceBuffer.h>
+#include <aidl/android/hardware/neuralnetworks/DeviceType.h>
+#include <aidl/android/hardware/neuralnetworks/ErrorStatus.h>
+#include <aidl/android/hardware/neuralnetworks/ExecutionPreference.h>
+#include <aidl/android/hardware/neuralnetworks/Extension.h>
+#include <aidl/android/hardware/neuralnetworks/ExtensionNameAndPrefix.h>
+#include <aidl/android/hardware/neuralnetworks/ExtensionOperandTypeInformation.h>
+#include <aidl/android/hardware/neuralnetworks/FusedActivationFunc.h>
+#include <aidl/android/hardware/neuralnetworks/IBuffer.h>
+#include <aidl/android/hardware/neuralnetworks/IDevice.h>
+#include <aidl/android/hardware/neuralnetworks/IFencedExecutionCallback.h>
+#include <aidl/android/hardware/neuralnetworks/IPreparedModel.h>
+#include <aidl/android/hardware/neuralnetworks/IPreparedModelCallback.h>
+#include <aidl/android/hardware/neuralnetworks/IPreparedModelParcel.h>
+#include <aidl/android/hardware/neuralnetworks/Memory.h>
+#include <aidl/android/hardware/neuralnetworks/Model.h>
+#include <aidl/android/hardware/neuralnetworks/NumberOfCacheFiles.h>
+#include <aidl/android/hardware/neuralnetworks/Operand.h>
+#include <aidl/android/hardware/neuralnetworks/OperandExtraParams.h>
+#include <aidl/android/hardware/neuralnetworks/OperandLifeTime.h>
+#include <aidl/android/hardware/neuralnetworks/OperandPerformance.h>
+#include <aidl/android/hardware/neuralnetworks/OperandType.h>
+#include <aidl/android/hardware/neuralnetworks/Operation.h>
+#include <aidl/android/hardware/neuralnetworks/OperationType.h>
+#include <aidl/android/hardware/neuralnetworks/OutputShape.h>
+#include <aidl/android/hardware/neuralnetworks/PerformanceInfo.h>
+#include <aidl/android/hardware/neuralnetworks/Priority.h>
+#include <aidl/android/hardware/neuralnetworks/Request.h>
+#include <aidl/android/hardware/neuralnetworks/RequestArgument.h>
+#include <aidl/android/hardware/neuralnetworks/RequestMemoryPool.h>
+#include <aidl/android/hardware/neuralnetworks/Subgraph.h>
+#include <aidl/android/hardware/neuralnetworks/SymmPerChannelQuantParams.h>
+#include <aidl/android/hardware/neuralnetworks/Timing.h>
+
+#ifdef NN_AIDL_V4_OR_ABOVE
+#include <aidl/android/hardware/neuralnetworks/BnExecution.h>
+#include <aidl/android/hardware/neuralnetworks/ExecutionConfig.h>
+#include <aidl/android/hardware/neuralnetworks/IExecution.h>
+#include <aidl/android/hardware/neuralnetworks/PrepareModelConfig.h>
+#endif  // NN_AIDL_V4_OR_ABOVE
+
+namespace android::nn {
+
+namespace aidl_hal = ::aidl::android::hardware::neuralnetworks;
+
+inline constexpr aidl_hal::Priority kDefaultPriorityAidl = aidl_hal::Priority::MEDIUM;
+
+}  // namespace android::nn
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_HAL_INTERFACES_H
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/HalUtils.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/HalUtils.h
new file mode 100644
index 0000000..89552bc
--- /dev/null
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/HalUtils.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_HAL_UTILS_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_HAL_UTILS_H
+
+#include <vector>
+
+#include "nnapi/hal/aidl/HalInterfaces.h"
+
+namespace android {
+namespace nn {
+
+// Return a vector with one entry for each non-extension OperandType except
+// SUBGRAPH, set to the specified PerformanceInfo value.  The vector will be
+// sorted by OperandType.
+//
+// Control flow (OperandType::SUBGRAPH) operation performance is specified
+// separately using Capabilities::ifPerformance and
+// Capabilities::whilePerformance.
+std::vector<aidl_hal::OperandPerformance> nonExtensionOperandPerformance(
+        aidl_hal::PerformanceInfo perf);
+
+// Update the vector entry corresponding to the specified OperandType with the
+// specified PerformanceInfo value.  The vector must already have an entry for
+// that OperandType, and must be sorted by OperandType.
+void update(std::vector<aidl_hal::OperandPerformance>* operandPerformance,
+            aidl_hal::OperandType type, aidl_hal::PerformanceInfo perf);
+
+// Returns true if an operand type is an extension type.
+bool isExtensionOperandType(aidl_hal::OperandType type);
+
+// Returns true if an operand type is a scalar type.
+bool isNonExtensionScalar(aidl_hal::OperandType type);
+
+}  // namespace nn
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_HAL_UTILS_H
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/InvalidDevice.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/InvalidDevice.h
index e66507a..9375c1d 100644
--- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/InvalidDevice.h
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/InvalidDevice.h
@@ -53,6 +53,9 @@
             const std::vector<ndk::ScopedFileDescriptor>& dataCache,
             const std::vector<uint8_t>& token,
             const std::shared_ptr<IPreparedModelCallback>& callback) override;
+    ndk::ScopedAStatus prepareModelWithConfig(
+            const Model& model, const PrepareModelConfig& config,
+            const std::shared_ptr<IPreparedModelCallback>& callback) override;
     ndk::ScopedAStatus prepareModelFromCache(
             int64_t deadline, const std::vector<ndk::ScopedFileDescriptor>& modelCache,
             const std::vector<ndk::ScopedFileDescriptor>& dataCache,
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/PreparedModel.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/PreparedModel.h
index 4035764..cb6a85b 100644
--- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/PreparedModel.h
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/PreparedModel.h
@@ -40,26 +40,33 @@
     struct PrivateConstructorTag {};
 
   public:
+    // featureLevel is for testing purposes.
     static nn::GeneralResult<std::shared_ptr<const PreparedModel>> create(
-            std::shared_ptr<aidl_hal::IPreparedModel> preparedModel);
+            std::shared_ptr<aidl_hal::IPreparedModel> preparedModel, nn::Version featureLevel);
 
     PreparedModel(PrivateConstructorTag tag,
-                  std::shared_ptr<aidl_hal::IPreparedModel> preparedModel);
+                  std::shared_ptr<aidl_hal::IPreparedModel> preparedModel,
+                  nn::Version featureLevel);
 
     nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
             const nn::Request& request, nn::MeasureTiming measure,
-            const nn::OptionalTimePoint& deadline,
-            const nn::OptionalDuration& loopTimeoutDuration) const override;
+            const nn::OptionalTimePoint& deadline, const nn::OptionalDuration& loopTimeoutDuration,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
 
     nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>> executeFenced(
             const nn::Request& request, const std::vector<nn::SyncFence>& waitFor,
             nn::MeasureTiming measure, const nn::OptionalTimePoint& deadline,
             const nn::OptionalDuration& loopTimeoutDuration,
-            const nn::OptionalDuration& timeoutDurationAfterFence) const override;
+            const nn::OptionalDuration& timeoutDurationAfterFence,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
 
     nn::GeneralResult<nn::SharedExecution> createReusableExecution(
             const nn::Request& request, nn::MeasureTiming measure,
-            const nn::OptionalDuration& loopTimeoutDuration) const override;
+            const nn::OptionalDuration& loopTimeoutDuration,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
 
     nn::GeneralResult<nn::SharedBurst> configureExecutionBurst() const override;
 
@@ -67,6 +74,8 @@
 
     nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> executeInternal(
             const Request& request, bool measure, int64_t deadline, int64_t loopTimeoutDuration,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix,
             const hal::utils::RequestRelocation& relocation) const;
 
     nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>>
@@ -74,10 +83,13 @@
                           const std::vector<ndk::ScopedFileDescriptor>& waitFor, bool measure,
                           int64_t deadline, int64_t loopTimeoutDuration,
                           int64_t timeoutDurationAfterFence,
+                          const std::vector<nn::TokenValuePair>& hints,
+                          const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix,
                           const hal::utils::RequestRelocation& relocation) const;
 
   private:
     const std::shared_ptr<aidl_hal::IPreparedModel> kPreparedModel;
+    const nn::Version kFeatureLevel;
 };
 
 }  // namespace aidl::android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/ProtectCallback.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/ProtectCallback.h
index ab1108c..92ed1cd 100644
--- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/ProtectCallback.h
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/ProtectCallback.h
@@ -23,7 +23,6 @@
 #include <nnapi/Result.h>
 #include <nnapi/Types.h>
 #include <nnapi/hal/CommonUtils.h>
-#include <nnapi/hal/ProtectCallback.h>
 
 #include <functional>
 #include <mutex>
@@ -34,19 +33,39 @@
 
 namespace aidl::android::hardware::neuralnetworks::utils {
 
+class IProtectedCallback {
+  public:
+    /**
+     * Marks this object as a dead object.
+     */
+    virtual void notifyAsDeadObject() = 0;
+
+    // Public virtual destructor to allow objects to be stored (and destroyed) as smart pointers.
+    // E.g., std::unique_ptr<IProtectedCallback>.
+    virtual ~IProtectedCallback() = default;
+
+  protected:
+    // Protect the non-destructor special member functions to prevent object slicing.
+    IProtectedCallback() = default;
+    IProtectedCallback(const IProtectedCallback&) = default;
+    IProtectedCallback(IProtectedCallback&&) noexcept = default;
+    IProtectedCallback& operator=(const IProtectedCallback&) = default;
+    IProtectedCallback& operator=(IProtectedCallback&&) noexcept = default;
+};
+
 // Thread safe class
 class DeathMonitor final {
   public:
     static void serviceDied(void* cookie);
     void serviceDied();
     // Precondition: `killable` must be non-null.
-    void add(hal::utils::IProtectedCallback* killable) const;
+    void add(IProtectedCallback* killable) const;
     // Precondition: `killable` must be non-null.
-    void remove(hal::utils::IProtectedCallback* killable) const;
+    void remove(IProtectedCallback* killable) const;
 
   private:
     mutable std::mutex mMutex;
-    mutable std::vector<hal::utils::IProtectedCallback*> mObjects GUARDED_BY(mMutex);
+    mutable std::vector<IProtectedCallback*> mObjects GUARDED_BY(mMutex);
 };
 
 class DeathHandler final {
@@ -62,7 +81,7 @@
     using Cleanup = std::function<void()>;
     // Precondition: `killable` must be non-null.
     [[nodiscard]] ::android::base::ScopeGuard<Cleanup> protectCallback(
-            hal::utils::IProtectedCallback* killable) const;
+            IProtectedCallback* killable) const;
 
     std::shared_ptr<DeathMonitor> getDeathMonitor() const { return kDeathMonitor; }
 
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Service.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Service.h
index cb6ff4b..f229165 100644
--- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Service.h
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Service.h
@@ -25,7 +25,8 @@
 
 namespace aidl::android::hardware::neuralnetworks::utils {
 
-::android::nn::GeneralResult<::android::nn::SharedDevice> getDevice(const std::string& name);
+::android::nn::GeneralResult<::android::nn::SharedDevice> getDevice(
+        const std::string& name, ::android::nn::Version::Level maxFeatureLevelAllowed);
 
 }  // namespace aidl::android::hardware::neuralnetworks::utils
 
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Utils.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Utils.h
index 72cf73e..7ed5437 100644
--- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Utils.h
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Utils.h
@@ -19,17 +19,35 @@
 
 #include "nnapi/hal/aidl/Conversions.h"
 
+#include <aidl/android/hardware/neuralnetworks/IDevice.h>
 #include <android-base/logging.h>
 #include <nnapi/Result.h>
 #include <nnapi/TypeUtils.h>
 #include <nnapi/Types.h>
 #include <nnapi/Validation.h>
-#include <nnapi/hal/HandleError.h>
+
+#include <type_traits>
 
 namespace aidl::android::hardware::neuralnetworks::utils {
 
 constexpr auto kDefaultPriority = Priority::MEDIUM;
-constexpr auto kVersion = nn::Version::FEATURE_LEVEL_6;
+
+constexpr std::optional<nn::Version> aidlVersionToCanonicalVersion(int aidlVersion) {
+    switch (aidlVersion) {
+        case 1:
+            return nn::kVersionFeatureLevel5;
+        case 2:
+            return nn::kVersionFeatureLevel6;
+        case 3:
+            return nn::kVersionFeatureLevel7;
+        case 4:
+            return nn::kVersionFeatureLevel8;
+        default:
+            return std::nullopt;
+    }
+}
+
+constexpr auto kVersion = aidlVersionToCanonicalVersion(IDevice::version).value();
 
 template <typename Type>
 nn::Result<void> validate(const Type& halObject) {
@@ -50,10 +68,9 @@
 }
 
 template <typename Type>
-nn::GeneralResult<void> compliantVersion(const Type& canonical) {
-    const auto version = NN_TRY(::android::hardware::neuralnetworks::utils::makeGeneralFailure(
-            nn::validate(canonical)));
-    if (version > kVersion) {
+nn::Result<void> compliantVersion(const Type& canonical) {
+    const auto version = NN_TRY(nn::validate(canonical));
+    if (!nn::isCompliantVersion(version, kVersion)) {
         return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion;
     }
     return {};
@@ -65,6 +82,11 @@
     return convert(NN_TRY(nn::convert(nonCanonicalObject)));
 }
 
+template <typename Type>
+constexpr std::underlying_type_t<Type> underlyingType(Type value) {
+    return static_cast<std::underlying_type_t<Type>>(value);
+}
+
 nn::GeneralResult<Memory> clone(const Memory& memory);
 nn::GeneralResult<Request> clone(const Request& request);
 nn::GeneralResult<RequestMemoryPool> clone(const RequestMemoryPool& requestPool);
@@ -76,6 +98,13 @@
     for (const auto status = handleTransportError(ret); !status.ok();) \
     return NN_ERROR(status.error().code) << status.error().message << ": "
 
+#define HANDLE_STATUS_AIDL(status)                                                            \
+    if (const ::android::nn::ErrorStatus canonical = ::android::nn::convert(status).value_or( \
+                ::android::nn::ErrorStatus::GENERAL_FAILURE);                                 \
+        canonical == ::android::nn::ErrorStatus::NONE) {                                      \
+    } else                                                                                    \
+        return NN_ERROR(canonical)
+
 }  // namespace aidl::android::hardware::neuralnetworks::utils
 
 #endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_H
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/ValidateHal.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/ValidateHal.h
new file mode 100644
index 0000000..62aba31
--- /dev/null
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/ValidateHal.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_VALIDATE_HAL_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_VALIDATE_HAL_H
+
+#include "nnapi/hal/aidl/HalInterfaces.h"
+
+#include <memory>
+#include <set>
+#include <tuple>
+#include <vector>
+
+#include <nnapi/TypeUtils.h>
+#include <nnapi/Validation.h>
+
+namespace android {
+namespace nn {
+
+using AidlHalPreparedModelRole = std::tuple<const aidl_hal::IPreparedModel*, IOType, uint32_t>;
+
+bool validateMemoryDesc(
+        const aidl_hal::BufferDesc& desc,
+        const std::vector<std::shared_ptr<aidl_hal::IPreparedModel>>& preparedModels,
+        const std::vector<aidl_hal::BufferRole>& inputRoles,
+        const std::vector<aidl_hal::BufferRole>& outputRoles,
+        std::function<const aidl_hal::Model*(const std::shared_ptr<aidl_hal::IPreparedModel>&)>
+                getModel,
+        std::set<AidlHalPreparedModelRole>* preparedModelRoles, aidl_hal::Operand* combinedOperand);
+
+}  // namespace nn
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_VALIDATE_HAL_H
diff --git a/neuralnetworks/aidl/utils/src/Buffer.cpp b/neuralnetworks/aidl/utils/src/Buffer.cpp
index c729a68..9af3c9e 100644
--- a/neuralnetworks/aidl/utils/src/Buffer.cpp
+++ b/neuralnetworks/aidl/utils/src/Buffer.cpp
@@ -22,7 +22,6 @@
 
 #include "Conversions.h"
 #include "Utils.h"
-#include "nnapi/hal/aidl/Conversions.h"
 
 #include <memory>
 #include <utility>
diff --git a/neuralnetworks/aidl/utils/src/BufferTracker.cpp b/neuralnetworks/aidl/utils/src/BufferTracker.cpp
new file mode 100644
index 0000000..94dc891
--- /dev/null
+++ b/neuralnetworks/aidl/utils/src/BufferTracker.cpp
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "BufferTracker.h"
+
+#include "HalInterfaces.h"
+
+#include <android-base/macros.h>
+#include <nnapi/TypeUtils.h>
+
+#include <memory>
+#include <mutex>
+#include <set>
+#include <stack>
+#include <utility>
+#include <vector>
+
+namespace android::nn {
+
+std::shared_ptr<AidlManagedBuffer> AidlManagedBuffer::create(
+        uint32_t size, std::set<AidlHalPreparedModelRole> roles, const Operand& operand) {
+    std::unique_ptr<uint8_t[]> buffer(new (std::nothrow) uint8_t[size]);
+    if (buffer == nullptr) {
+        return nullptr;
+    }
+    if (isExtension(operand.type)) {
+        LOG(ERROR) << "AidlManagedBuffer cannot handle extension operands.";
+        return nullptr;
+    }
+    return std::make_shared<AidlManagedBuffer>(std::move(buffer), size, std::move(roles), operand);
+}
+
+AidlManagedBuffer::AidlManagedBuffer(std::unique_ptr<uint8_t[]> buffer, uint32_t size,
+                                     std::set<AidlHalPreparedModelRole> roles,
+                                     const Operand& operand)
+    : kBuffer(std::move(buffer)),
+      kSize(size),
+      kRoles(std::move(roles)),
+      kOperandType(operand.type),
+      kInitialDimensions(operand.dimensions),
+      mUpdatedDimensions(operand.dimensions) {
+    CHECK(!isExtension(kOperandType));
+}
+
+ErrorStatus AidlManagedBuffer::validateRequest(
+        uint32_t poolIndex, const Request& request,
+        const aidl_hal::IPreparedModel* preparedModel) const {
+    CHECK_LT(poolIndex, request.pools.size());
+    CHECK(std::holds_alternative<Request::MemoryDomainToken>(request.pools[poolIndex]));
+    std::lock_guard<std::mutex> guard(mMutex);
+
+    bool usedAsInput = false, usedAsOutput = false;
+    for (uint32_t i = 0; i < request.inputs.size(); i++) {
+        if (request.inputs[i].lifetime != Request::Argument::LifeTime::POOL) continue;
+        if (request.inputs[i].location.poolIndex != poolIndex) continue;
+        // Validate if the input role is specified during allocation.
+        if (kRoles.count({preparedModel, IOType::INPUT, i}) == 0) {
+            LOG(ERROR) << "AidlManagedBuffer::validateRequest -- invalid buffer role.";
+            return ErrorStatus::INVALID_ARGUMENT;
+        }
+        if (!mInitialized) {
+            LOG(ERROR)
+                    << "AidlManagedBuffer::validateRequest -- using uninitialized buffer as input "
+                       "request.";
+            return ErrorStatus::GENERAL_FAILURE;
+        }
+        auto combined = combineDimensions(mUpdatedDimensions, request.inputs[i].dimensions);
+        if (!combined.has_value()) {
+            LOG(ERROR) << "AidlManagedBuffer::validateRequest -- incompatible dimensions ("
+                       << toString(mUpdatedDimensions) << " vs "
+                       << toString(request.inputs[i].dimensions) << ")";
+            return ErrorStatus::INVALID_ARGUMENT;
+        }
+        usedAsInput = true;
+    }
+    for (uint32_t i = 0; i < request.outputs.size(); i++) {
+        if (request.outputs[i].lifetime != Request::Argument::LifeTime::POOL) continue;
+        if (request.outputs[i].location.poolIndex != poolIndex) continue;
+        if (usedAsInput || usedAsOutput) {
+            LOG(ERROR) << "AidlManagedBuffer::validateRequest -- using the same device memory for "
+                          "input/output or multiple outputs";
+            return ErrorStatus::INVALID_ARGUMENT;
+        }
+        // Validate if the output role is specified during allocation.
+        if (kRoles.count({preparedModel, IOType::OUTPUT, i}) == 0) {
+            LOG(ERROR) << "AidlManagedBuffer::validateRequest -- invalid buffer role.";
+            return ErrorStatus::INVALID_ARGUMENT;
+        }
+        auto combined = combineDimensions(kInitialDimensions, request.outputs[i].dimensions);
+        if (!combined.has_value()) {
+            LOG(ERROR) << "AidlManagedBuffer::validateRequest -- incompatible dimensions ("
+                       << toString(kInitialDimensions) << " vs "
+                       << toString(request.outputs[i].dimensions) << ")";
+            return ErrorStatus::INVALID_ARGUMENT;
+        }
+        usedAsOutput = true;
+    }
+    return ErrorStatus::NONE;
+}
+
+ErrorStatus AidlManagedBuffer::validateCopyFrom(const std::vector<uint32_t>& dimensions,
+                                                uint32_t size) const {
+    if (size != kSize) {
+        LOG(ERROR) << "AidlManagedBuffer::validateCopyFrom -- invalid memory size: " << kSize
+                   << " vs " << size;
+        return ErrorStatus::INVALID_ARGUMENT;
+    }
+
+    if (isNonExtensionScalar(kOperandType)) {
+        if (!dimensions.empty()) {
+            LOG(ERROR) << "AidlManagedBuffer::validateCopyFrom -- invalid dimensions for scalar "
+                          "operand: "
+                       << toString(dimensions);
+            return ErrorStatus::INVALID_ARGUMENT;
+        }
+        return ErrorStatus::NONE;
+    }
+
+    if (dimensions.empty()) {
+        if (tensorHasUnspecifiedDimensions(kOperandType, kInitialDimensions)) {
+            LOG(ERROR) << "AidlManagedBuffer::validateCopyFrom -- the initial dimensions are not "
+                          "fully "
+                          "specified and no dimension update is provided: "
+                       << toString(kInitialDimensions);
+            return ErrorStatus::INVALID_ARGUMENT;
+        }
+    } else {
+        if (tensorHasUnspecifiedDimensions(kOperandType, dimensions)) {
+            LOG(ERROR) << "AidlManagedBuffer::validateCopyFrom -- the updated dimensions are not "
+                          "fully "
+                          "specified: "
+                       << toString(dimensions);
+            return ErrorStatus::INVALID_ARGUMENT;
+        }
+    }
+
+    const auto combined = combineDimensions(kInitialDimensions, dimensions);
+    if (!combined.has_value()) {
+        LOG(ERROR) << "AidlManagedBuffer::validateCopyFrom -- incompatible dimensions ("
+                   << toString(kInitialDimensions) << " vs " << toString(dimensions) << ")";
+        return ErrorStatus::INVALID_ARGUMENT;
+    }
+    return ErrorStatus::NONE;
+}
+
+ErrorStatus AidlManagedBuffer::validateCopyTo(uint32_t size) const {
+    if (size != kSize) {
+        LOG(ERROR) << "AidlManagedBuffer::validateCopyTo -- invalid memory size: " << kSize
+                   << " vs " << size;
+        return ErrorStatus::INVALID_ARGUMENT;
+    }
+    std::lock_guard<std::mutex> guard(mMutex);
+    if (!mInitialized) {
+        LOG(ERROR) << "AidlManagedBuffer::validateCopyTo -- using uninitialized buffer as source.";
+        return ErrorStatus::GENERAL_FAILURE;
+    }
+    return ErrorStatus::NONE;
+}
+
+bool AidlManagedBuffer::updateDimensions(const std::vector<uint32_t>& dimensions) {
+    auto combined = combineDimensions(kInitialDimensions, dimensions);
+    if (!combined.has_value()) {
+        LOG(ERROR) << "AidlManagedBuffer::updateDimensions -- incompatible dimensions ("
+                   << toString(kInitialDimensions) << " vs " << toString(dimensions) << ")";
+        return false;
+    }
+    std::lock_guard<std::mutex> guard(mMutex);
+    mUpdatedDimensions = std::move(combined).value();
+    return true;
+}
+
+void AidlManagedBuffer::setInitialized(bool initialized) {
+    std::lock_guard<std::mutex> guard(mMutex);
+    mInitialized = initialized;
+}
+
+std::unique_ptr<AidlBufferTracker::Token> AidlBufferTracker::add(
+        std::shared_ptr<AidlManagedBuffer> buffer) {
+    if (buffer == nullptr) {
+        return nullptr;
+    }
+    std::lock_guard<std::mutex> guard(mMutex);
+    uint32_t token = 0;
+    if (mFreeTokens.empty()) {
+        token = mTokenToBuffers.size();
+        mTokenToBuffers.push_back(std::move(buffer));
+    } else {
+        token = mFreeTokens.top();
+        mFreeTokens.pop();
+        mTokenToBuffers[token] = std::move(buffer);
+    }
+    VLOG(MEMORY) << "AidlBufferTracker::add -- new token = " << token;
+    return std::make_unique<Token>(token, shared_from_this());
+}
+
+std::shared_ptr<AidlManagedBuffer> AidlBufferTracker::get(uint32_t token) const {
+    std::lock_guard<std::mutex> guard(mMutex);
+    if (mTokenToBuffers.size() <= token || mTokenToBuffers[token] == nullptr) {
+        LOG(ERROR) << "AidlBufferTracker::get -- unknown token " << token;
+        return nullptr;
+    }
+    return mTokenToBuffers[token];
+}
+
+void AidlBufferTracker::free(uint32_t token) {
+    std::lock_guard<std::mutex> guard(mMutex);
+    CHECK_LT(token, mTokenToBuffers.size());
+    CHECK(mTokenToBuffers[token] != nullptr);
+    VLOG(MEMORY) << "AidlBufferTracker::free -- release token = " << token;
+    mTokenToBuffers[token] = nullptr;
+    mFreeTokens.push(token);
+}
+
+}  // namespace android::nn
diff --git a/neuralnetworks/aidl/utils/src/Burst.cpp b/neuralnetworks/aidl/utils/src/Burst.cpp
index 800ac32..6c7aa88 100644
--- a/neuralnetworks/aidl/utils/src/Burst.cpp
+++ b/neuralnetworks/aidl/utils/src/Burst.cpp
@@ -26,7 +26,6 @@
 #include <nnapi/Result.h>
 #include <nnapi/TypeUtils.h>
 #include <nnapi/Types.h>
-#include <nnapi/hal/HandleError.h>
 
 #include <memory>
 #include <mutex>
@@ -44,12 +43,16 @@
     static nn::GeneralResult<std::shared_ptr<const BurstExecution>> create(
             std::shared_ptr<const Burst> burst, Request request,
             std::vector<int64_t> memoryIdentifierTokens, bool measure, int64_t loopTimeoutDuration,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix,
             hal::utils::RequestRelocation relocation,
             std::vector<Burst::OptionalCacheHold> cacheHolds);
 
     BurstExecution(PrivateConstructorTag tag, std::shared_ptr<const Burst> burst, Request request,
                    std::vector<int64_t> memoryIdentifierTokens, bool measure,
-                   int64_t loopTimeoutDuration, hal::utils::RequestRelocation relocation,
+                   int64_t loopTimeoutDuration, const std::vector<nn::TokenValuePair>& hints,
+                   const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix,
+                   hal::utils::RequestRelocation relocation,
                    std::vector<Burst::OptionalCacheHold> cacheHolds);
 
     nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> compute(
@@ -65,6 +68,8 @@
     const std::vector<int64_t> kMemoryIdentifierTokens;
     const bool kMeasure;
     const int64_t kLoopTimeoutDuration;
+    const std::vector<nn::TokenValuePair> kHints;
+    const std::vector<nn::ExtensionNameAndPrefix> kExtensionNameToPrefix;
     const hal::utils::RequestRelocation kRelocation;
     const std::vector<Burst::OptionalCacheHold> kCacheHolds;
 };
@@ -150,17 +155,20 @@
 }
 
 nn::GeneralResult<std::shared_ptr<const Burst>> Burst::create(
-        std::shared_ptr<aidl_hal::IBurst> burst) {
+        std::shared_ptr<aidl_hal::IBurst> burst, nn::Version featureLevel) {
     if (burst == nullptr) {
         return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
                << "aidl_hal::utils::Burst::create must have non-null burst";
     }
 
-    return std::make_shared<const Burst>(PrivateConstructorTag{}, std::move(burst));
+    return std::make_shared<const Burst>(PrivateConstructorTag{}, std::move(burst), featureLevel);
 }
 
-Burst::Burst(PrivateConstructorTag /*tag*/, std::shared_ptr<aidl_hal::IBurst> burst)
-    : kBurst(std::move(burst)), kMemoryCache(std::make_shared<MemoryCache>(kBurst)) {
+Burst::Burst(PrivateConstructorTag /*tag*/, std::shared_ptr<aidl_hal::IBurst> burst,
+             nn::Version featureLevel)
+    : kBurst(std::move(burst)),
+      kMemoryCache(std::make_shared<MemoryCache>(kBurst)),
+      kFeatureLevel(featureLevel) {
     CHECK(kBurst != nullptr);
 }
 
@@ -171,21 +179,20 @@
 
 nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> Burst::execute(
         const nn::Request& request, nn::MeasureTiming measure,
-        const nn::OptionalTimePoint& deadline,
-        const nn::OptionalDuration& loopTimeoutDuration) const {
+        const nn::OptionalTimePoint& deadline, const nn::OptionalDuration& loopTimeoutDuration,
+        const std::vector<nn::TokenValuePair>& hints,
+        const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const {
     // Ensure that request is ready for IPC.
     std::optional<nn::Request> maybeRequestInShared;
     hal::utils::RequestRelocation relocation;
-    const nn::Request& requestInShared =
-            NN_TRY(hal::utils::makeExecutionFailure(hal::utils::convertRequestFromPointerToShared(
-                    &request, nn::kDefaultRequestMemoryAlignment, nn::kDefaultRequestMemoryPadding,
-                    &maybeRequestInShared, &relocation)));
+    const nn::Request& requestInShared = NN_TRY(hal::utils::convertRequestFromPointerToShared(
+            &request, nn::kDefaultRequestMemoryAlignment, nn::kDefaultRequestMemoryPadding,
+            &maybeRequestInShared, &relocation));
 
-    const auto aidlRequest = NN_TRY(hal::utils::makeExecutionFailure(convert(requestInShared)));
-    const auto aidlMeasure = NN_TRY(hal::utils::makeExecutionFailure(convert(measure)));
-    const auto aidlDeadline = NN_TRY(hal::utils::makeExecutionFailure(convert(deadline)));
-    const auto aidlLoopTimeoutDuration =
-            NN_TRY(hal::utils::makeExecutionFailure(convert(loopTimeoutDuration)));
+    const auto aidlRequest = NN_TRY(convert(requestInShared));
+    const auto aidlMeasure = NN_TRY(convert(measure));
+    const auto aidlDeadline = NN_TRY(convert(deadline));
+    const auto aidlLoopTimeoutDuration = NN_TRY(convert(loopTimeoutDuration));
 
     std::vector<int64_t> memoryIdentifierTokens;
     std::vector<OptionalCacheHold> holds;
@@ -203,14 +210,14 @@
         memoryIdentifierTokens.push_back(-1);
     }
     CHECK_EQ(requestInShared.pools.size(), memoryIdentifierTokens.size());
-
     return executeInternal(aidlRequest, memoryIdentifierTokens, aidlMeasure, aidlDeadline,
-                           aidlLoopTimeoutDuration, relocation);
+                           aidlLoopTimeoutDuration, hints, extensionNameToPrefix, relocation);
 }
 
 nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> Burst::executeInternal(
         const Request& request, const std::vector<int64_t>& memoryIdentifierTokens, bool measure,
-        int64_t deadline, int64_t loopTimeoutDuration,
+        int64_t deadline, int64_t loopTimeoutDuration, const std::vector<nn::TokenValuePair>& hints,
+        const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix,
         const hal::utils::RequestRelocation& relocation) const {
     // Ensure that at most one execution is in flight at any given time.
     const bool alreadyInFlight = mExecutionInFlight.test_and_set();
@@ -224,17 +231,29 @@
     }
 
     ExecutionResult executionResult;
-    const auto ret = kBurst->executeSynchronously(request, memoryIdentifierTokens, measure,
-                                                  deadline, loopTimeoutDuration, &executionResult);
-    HANDLE_ASTATUS(ret) << "execute failed";
+    if (kFeatureLevel.level >= nn::Version::Level::FEATURE_LEVEL_8) {
+        auto aidlHints = NN_TRY(convert(hints));
+        auto aidlExtensionPrefix = NN_TRY(convert(extensionNameToPrefix));
+        const auto ret = kBurst->executeSynchronouslyWithConfig(
+                request, memoryIdentifierTokens,
+                {measure, loopTimeoutDuration, std::move(aidlHints),
+                 std::move(aidlExtensionPrefix)},
+                deadline, &executionResult);
+        HANDLE_ASTATUS(ret) << "execute failed";
+    } else {
+        const auto ret =
+                kBurst->executeSynchronously(request, memoryIdentifierTokens, measure, deadline,
+                                             loopTimeoutDuration, &executionResult);
+        HANDLE_ASTATUS(ret) << "execute failed";
+    }
     if (!executionResult.outputSufficientSize) {
         auto canonicalOutputShapes =
                 nn::convert(executionResult.outputShapes).value_or(std::vector<nn::OutputShape>{});
         return NN_ERROR(nn::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE, std::move(canonicalOutputShapes))
                << "execution failed with " << nn::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE;
     }
-    auto [outputShapes, timing] = NN_TRY(hal::utils::makeExecutionFailure(
-            convertExecutionResults(executionResult.outputShapes, executionResult.timing)));
+    auto [outputShapes, timing] =
+            NN_TRY(convertExecutionResults(executionResult.outputShapes, executionResult.timing));
 
     if (relocation.output) {
         relocation.output->flush();
@@ -244,7 +263,9 @@
 
 nn::GeneralResult<nn::SharedExecution> Burst::createReusableExecution(
         const nn::Request& request, nn::MeasureTiming measure,
-        const nn::OptionalDuration& loopTimeoutDuration) const {
+        const nn::OptionalDuration& loopTimeoutDuration,
+        const std::vector<nn::TokenValuePair>& hints,
+        const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const {
     // Ensure that request is ready for IPC.
     std::optional<nn::Request> maybeRequestInShared;
     hal::utils::RequestRelocation relocation;
@@ -275,12 +296,15 @@
 
     return BurstExecution::create(shared_from_this(), std::move(aidlRequest),
                                   std::move(memoryIdentifierTokens), aidlMeasure,
-                                  aidlLoopTimeoutDuration, std::move(relocation), std::move(holds));
+                                  aidlLoopTimeoutDuration, hints, extensionNameToPrefix,
+                                  std::move(relocation), std::move(holds));
 }
 
 nn::GeneralResult<std::shared_ptr<const BurstExecution>> BurstExecution::create(
         std::shared_ptr<const Burst> burst, Request request,
         std::vector<int64_t> memoryIdentifierTokens, bool measure, int64_t loopTimeoutDuration,
+        const std::vector<nn::TokenValuePair>& hints,
+        const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix,
         hal::utils::RequestRelocation relocation,
         std::vector<Burst::OptionalCacheHold> cacheHolds) {
     if (burst == nullptr) {
@@ -289,13 +313,15 @@
 
     return std::make_shared<const BurstExecution>(
             PrivateConstructorTag{}, std::move(burst), std::move(request),
-            std::move(memoryIdentifierTokens), measure, loopTimeoutDuration, std::move(relocation),
-            std::move(cacheHolds));
+            std::move(memoryIdentifierTokens), measure, loopTimeoutDuration, hints,
+            extensionNameToPrefix, std::move(relocation), std::move(cacheHolds));
 }
 
 BurstExecution::BurstExecution(PrivateConstructorTag /*tag*/, std::shared_ptr<const Burst> burst,
                                Request request, std::vector<int64_t> memoryIdentifierTokens,
                                bool measure, int64_t loopTimeoutDuration,
+                               const std::vector<nn::TokenValuePair>& hints,
+                               const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix,
                                hal::utils::RequestRelocation relocation,
                                std::vector<Burst::OptionalCacheHold> cacheHolds)
     : kBurst(std::move(burst)),
@@ -303,14 +329,17 @@
       kMemoryIdentifierTokens(std::move(memoryIdentifierTokens)),
       kMeasure(measure),
       kLoopTimeoutDuration(loopTimeoutDuration),
+      kHints(hints),
+      kExtensionNameToPrefix(extensionNameToPrefix),
       kRelocation(std::move(relocation)),
       kCacheHolds(std::move(cacheHolds)) {}
 
 nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> BurstExecution::compute(
         const nn::OptionalTimePoint& deadline) const {
-    const auto aidlDeadline = NN_TRY(hal::utils::makeExecutionFailure(convert(deadline)));
+    const auto aidlDeadline = NN_TRY(convert(deadline));
     return kBurst->executeInternal(kRequest, kMemoryIdentifierTokens, kMeasure, aidlDeadline,
-                                   kLoopTimeoutDuration, kRelocation);
+                                   kLoopTimeoutDuration, kHints, kExtensionNameToPrefix,
+                                   kRelocation);
 }
 
 nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>>
diff --git a/neuralnetworks/aidl/utils/src/Callbacks.cpp b/neuralnetworks/aidl/utils/src/Callbacks.cpp
index 8055665..554f3fa 100644
--- a/neuralnetworks/aidl/utils/src/Callbacks.cpp
+++ b/neuralnetworks/aidl/utils/src/Callbacks.cpp
@@ -35,18 +35,20 @@
 
 // Converts the results of IDevice::prepareModel* to the NN canonical format. On success, this
 // function returns with a non-null nn::SharedPreparedModel with a feature level of
-// nn::Version::ANDROID_S. On failure, this function returns with the appropriate nn::GeneralError.
+// nn::kVersionFeatureLevel5. On failure, this function returns with the appropriate
+// nn::GeneralError.
 nn::GeneralResult<nn::SharedPreparedModel> prepareModelCallback(
-        ErrorStatus status, const std::shared_ptr<IPreparedModel>& preparedModel) {
-    HANDLE_HAL_STATUS(status) << "model preparation failed with " << toString(status);
-    return NN_TRY(PreparedModel::create(preparedModel));
+        ErrorStatus status, const std::shared_ptr<IPreparedModel>& preparedModel,
+        nn::Version featureLevel) {
+    HANDLE_STATUS_AIDL(status) << "model preparation failed with " << toString(status);
+    return NN_TRY(PreparedModel::create(preparedModel, featureLevel));
 }
 
 }  // namespace
 
 ndk::ScopedAStatus PreparedModelCallback::notify(
         ErrorStatus status, const std::shared_ptr<IPreparedModel>& preparedModel) {
-    mData.put(prepareModelCallback(status, preparedModel));
+    mData.put(prepareModelCallback(status, preparedModel, kFeatureLevel));
     return ndk::ScopedAStatus::ok();
 }
 
diff --git a/neuralnetworks/aidl/utils/src/Conversions.cpp b/neuralnetworks/aidl/utils/src/Conversions.cpp
index 4b263ee..47c72b4 100644
--- a/neuralnetworks/aidl/utils/src/Conversions.cpp
+++ b/neuralnetworks/aidl/utils/src/Conversions.cpp
@@ -25,7 +25,6 @@
 #include <android-base/mapped_file.h>
 #include <android-base/unique_fd.h>
 #include <android/binder_auto_utils.h>
-#include <android/hardware_buffer.h>
 #include <cutils/native_handle.h>
 #include <nnapi/OperandTypes.h>
 #include <nnapi/OperationTypes.h>
@@ -35,8 +34,6 @@
 #include <nnapi/Types.h>
 #include <nnapi/Validation.h>
 #include <nnapi/hal/CommonUtils.h>
-#include <nnapi/hal/HandleError.h>
-#include <vndk/hardware_buffer.h>
 
 #include <algorithm>
 #include <chrono>
@@ -48,6 +45,11 @@
 
 #include "Utils.h"
 
+#ifdef __ANDROID__
+#include <android/hardware_buffer.h>
+#include <vndk/hardware_buffer.h>
+#endif  // __ANDROID__
+
 #define VERIFY_NON_NEGATIVE(value) \
     while (UNLIKELY(value < 0)) return NN_ERROR()
 
@@ -55,10 +57,6 @@
     while (UNLIKELY(value > std::numeric_limits<int32_t>::max())) return NN_ERROR()
 
 namespace {
-template <typename Type>
-constexpr std::underlying_type_t<Type> underlyingType(Type value) {
-    return static_cast<std::underlying_type_t<Type>>(value);
-}
 
 constexpr int64_t kNoTiming = -1;
 
@@ -68,6 +66,7 @@
 namespace {
 
 using ::aidl::android::hardware::common::NativeHandle;
+using ::aidl::android::hardware::neuralnetworks::utils::underlyingType;
 
 template <typename Input>
 using UnvalidatedConvertOutput =
@@ -108,17 +107,6 @@
     return canonical;
 }
 
-GeneralResult<Handle> unvalidatedConvertHelper(const NativeHandle& aidlNativeHandle) {
-    std::vector<base::unique_fd> fds;
-    fds.reserve(aidlNativeHandle.fds.size());
-    for (const auto& fd : aidlNativeHandle.fds) {
-        auto duplicatedFd = NN_TRY(dupFd(fd.get()));
-        fds.emplace_back(duplicatedFd.release());
-    }
-
-    return Handle{.fds = std::move(fds), .ints = aidlNativeHandle.ints};
-}
-
 struct NativeHandleDeleter {
     void operator()(native_handle_t* handle) const {
         if (handle) {
@@ -130,6 +118,7 @@
 
 using UniqueNativeHandle = std::unique_ptr<native_handle_t, NativeHandleDeleter>;
 
+#ifdef __ANDROID__
 GeneralResult<UniqueNativeHandle> nativeHandleFromAidlHandle(const NativeHandle& handle) {
     auto nativeHandle = UniqueNativeHandle(dupFromAidl(handle));
     if (nativeHandle.get() == nullptr) {
@@ -142,6 +131,7 @@
     }
     return nativeHandle;
 }
+#endif  // __ANDROID__
 
 }  // anonymous namespace
 
@@ -184,26 +174,31 @@
     }
 
     auto operandPerformance = NN_TRY(unvalidatedConvert(capabilities.operandPerformance));
-    auto table = NN_TRY(hal::utils::makeGeneralFailure(
-            Capabilities::OperandPerformanceTable::create(std::move(operandPerformance)),
-            nn::ErrorStatus::GENERAL_FAILURE));
+    auto table =
+            NN_TRY(Capabilities::OperandPerformanceTable::create(std::move(operandPerformance)));
 
+    const auto relaxedFloat32toFloat16PerformanceScalar =
+            NN_TRY(unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceScalar));
+    const auto relaxedFloat32toFloat16PerformanceTensor =
+            NN_TRY(unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor));
+    const auto ifPerformance = NN_TRY(unvalidatedConvert(capabilities.ifPerformance));
+    const auto whilePerformance = NN_TRY(unvalidatedConvert(capabilities.whilePerformance));
     return Capabilities{
-            .relaxedFloat32toFloat16PerformanceScalar = NN_TRY(
-                    unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceScalar)),
-            .relaxedFloat32toFloat16PerformanceTensor = NN_TRY(
-                    unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor)),
+            .relaxedFloat32toFloat16PerformanceScalar = relaxedFloat32toFloat16PerformanceScalar,
+            .relaxedFloat32toFloat16PerformanceTensor = relaxedFloat32toFloat16PerformanceTensor,
             .operandPerformance = std::move(table),
-            .ifPerformance = NN_TRY(unvalidatedConvert(capabilities.ifPerformance)),
-            .whilePerformance = NN_TRY(unvalidatedConvert(capabilities.whilePerformance)),
+            .ifPerformance = ifPerformance,
+            .whilePerformance = whilePerformance,
     };
 }
 
 GeneralResult<Capabilities::OperandPerformance> unvalidatedConvert(
         const aidl_hal::OperandPerformance& operandPerformance) {
+    const auto type = NN_TRY(unvalidatedConvert(operandPerformance.type));
+    const auto info = NN_TRY(unvalidatedConvert(operandPerformance.info));
     return Capabilities::OperandPerformance{
-            .type = NN_TRY(unvalidatedConvert(operandPerformance.type)),
-            .info = NN_TRY(unvalidatedConvert(operandPerformance.info)),
+            .type = type,
+            .info = info,
     };
 }
 
@@ -239,10 +234,13 @@
 }
 
 GeneralResult<Operation> unvalidatedConvert(const aidl_hal::Operation& operation) {
+    const auto type = NN_TRY(unvalidatedConvert(operation.type));
+    auto inputs = NN_TRY(toUnsigned(operation.inputs));
+    auto outputs = NN_TRY(toUnsigned(operation.outputs));
     return Operation{
-            .type = NN_TRY(unvalidatedConvert(operation.type)),
-            .inputs = NN_TRY(toUnsigned(operation.inputs)),
-            .outputs = NN_TRY(toUnsigned(operation.outputs)),
+            .type = type,
+            .inputs = std::move(inputs),
+            .outputs = std::move(outputs),
     };
 }
 
@@ -252,14 +250,19 @@
 }
 
 GeneralResult<Operand> unvalidatedConvert(const aidl_hal::Operand& operand) {
+    const auto type = NN_TRY(unvalidatedConvert(operand.type));
+    auto dimensions = NN_TRY(toUnsigned(operand.dimensions));
+    const auto lifetime = NN_TRY(unvalidatedConvert(operand.lifetime));
+    const auto location = NN_TRY(unvalidatedConvert(operand.location));
+    auto extraParams = NN_TRY(unvalidatedConvert(operand.extraParams));
     return Operand{
-            .type = NN_TRY(unvalidatedConvert(operand.type)),
-            .dimensions = NN_TRY(toUnsigned(operand.dimensions)),
+            .type = type,
+            .dimensions = std::move(dimensions),
             .scale = operand.scale,
             .zeroPoint = operand.zeroPoint,
-            .lifetime = NN_TRY(unvalidatedConvert(operand.lifetime)),
-            .location = NN_TRY(unvalidatedConvert(operand.location)),
-            .extraParams = NN_TRY(unvalidatedConvert(operand.extraParams)),
+            .lifetime = lifetime,
+            .location = location,
+            .extraParams = std::move(extraParams),
     };
 }
 
@@ -291,37 +294,47 @@
 }
 
 GeneralResult<Model> unvalidatedConvert(const aidl_hal::Model& model) {
+    auto main = NN_TRY(unvalidatedConvert(model.main));
+    auto referenced = NN_TRY(unvalidatedConvert(model.referenced));
+    auto operandValues = NN_TRY(unvalidatedConvert(model.operandValues));
+    auto pools = NN_TRY(unvalidatedConvert(model.pools));
+    auto extensionNameToPrefix = NN_TRY(unvalidatedConvert(model.extensionNameToPrefix));
     return Model{
-            .main = NN_TRY(unvalidatedConvert(model.main)),
-            .referenced = NN_TRY(unvalidatedConvert(model.referenced)),
-            .operandValues = NN_TRY(unvalidatedConvert(model.operandValues)),
-            .pools = NN_TRY(unvalidatedConvert(model.pools)),
+            .main = std::move(main),
+            .referenced = std::move(referenced),
+            .operandValues = std::move(operandValues),
+            .pools = std::move(pools),
             .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
-            .extensionNameToPrefix = NN_TRY(unvalidatedConvert(model.extensionNameToPrefix)),
+            .extensionNameToPrefix = std::move(extensionNameToPrefix),
     };
 }
 
 GeneralResult<Model::Subgraph> unvalidatedConvert(const aidl_hal::Subgraph& subgraph) {
+    auto operands = NN_TRY(unvalidatedConvert(subgraph.operands));
+    auto operations = NN_TRY(unvalidatedConvert(subgraph.operations));
+    auto inputIndexes = NN_TRY(toUnsigned(subgraph.inputIndexes));
+    auto outputIndexes = NN_TRY(toUnsigned(subgraph.outputIndexes));
     return Model::Subgraph{
-            .operands = NN_TRY(unvalidatedConvert(subgraph.operands)),
-            .operations = NN_TRY(unvalidatedConvert(subgraph.operations)),
-            .inputIndexes = NN_TRY(toUnsigned(subgraph.inputIndexes)),
-            .outputIndexes = NN_TRY(toUnsigned(subgraph.outputIndexes)),
+            .operands = std::move(operands),
+            .operations = std::move(operations),
+            .inputIndexes = std::move(inputIndexes),
+            .outputIndexes = std::move(outputIndexes),
     };
 }
 
-GeneralResult<Model::ExtensionNameAndPrefix> unvalidatedConvert(
+GeneralResult<ExtensionNameAndPrefix> unvalidatedConvert(
         const aidl_hal::ExtensionNameAndPrefix& extensionNameAndPrefix) {
-    return Model::ExtensionNameAndPrefix{
+    return ExtensionNameAndPrefix{
             .name = extensionNameAndPrefix.name,
             .prefix = extensionNameAndPrefix.prefix,
     };
 }
 
 GeneralResult<Extension> unvalidatedConvert(const aidl_hal::Extension& extension) {
+    auto operandTypes = NN_TRY(unvalidatedConvert(extension.operandTypes));
     return Extension{
             .name = extension.name,
-            .operandTypes = NN_TRY(unvalidatedConvert(extension.operandTypes)),
+            .operandTypes = std::move(operandTypes),
     };
 }
 
@@ -337,8 +350,9 @@
 }
 
 GeneralResult<OutputShape> unvalidatedConvert(const aidl_hal::OutputShape& outputShape) {
+    auto dimensions = NN_TRY(toUnsigned(outputShape.dimensions));
     return OutputShape{
-            .dimensions = NN_TRY(toUnsigned(outputShape.dimensions)),
+            .dimensions = std::move(dimensions),
             .isSufficient = outputShape.isSufficient,
     };
 }
@@ -357,8 +371,9 @@
                 return NN_ERROR() << "Memory: size must be <= std::numeric_limits<size_t>::max()";
             }
 
+            auto fd = NN_TRY(dupFd(ashmem.fd.get()));
             auto handle = Memory::Ashmem{
-                    .fd = NN_TRY(dupFd(ashmem.fd.get())),
+                    .fd = std::move(fd),
                     .size = static_cast<size_t>(ashmem.size),
             };
             return std::make_shared<const Memory>(Memory{.handle = std::move(handle)});
@@ -382,6 +397,7 @@
             return createSharedMemoryFromFd(size, prot, fd, offset);
         }
         case Tag::hardwareBuffer: {
+#ifdef __ANDROID__
             const auto& hardwareBuffer = memory.get<Tag::hardwareBuffer>();
 
             const UniqueNativeHandle handle =
@@ -404,9 +420,14 @@
             }
 
             return createSharedMemoryFromAHWB(ahwb, /*takeOwnership=*/true);
+#else   // __ANDROID__
+            LOG(FATAL) << "GeneralResult<SharedMemory> unvalidatedConvert(const aidl_hal::Memory& "
+                          "memory): Not Available on Host Build";
+            return NN_ERROR() << "createFromHandle failed";
+#endif  // __ANDROID__
         }
     }
-    return NN_ERROR() << "Unrecognized Memory::Tag: " << memory.getTag();
+    return NN_ERROR() << "Unrecognized Memory::Tag: " << underlyingType(memory.getTag());
 }
 
 GeneralResult<Timing> unvalidatedConvert(const aidl_hal::Timing& timing) {
@@ -431,7 +452,8 @@
 }
 
 GeneralResult<BufferDesc> unvalidatedConvert(const aidl_hal::BufferDesc& bufferDesc) {
-    return BufferDesc{.dimensions = NN_TRY(toUnsigned(bufferDesc.dimensions))};
+    auto dimensions = NN_TRY(toUnsigned(bufferDesc.dimensions));
+    return BufferDesc{.dimensions = std::move(dimensions)};
 }
 
 GeneralResult<BufferRole> unvalidatedConvert(const aidl_hal::BufferRole& bufferRole) {
@@ -445,20 +467,25 @@
 }
 
 GeneralResult<Request> unvalidatedConvert(const aidl_hal::Request& request) {
+    auto inputs = NN_TRY(unvalidatedConvert(request.inputs));
+    auto outputs = NN_TRY(unvalidatedConvert(request.outputs));
+    auto pools = NN_TRY(unvalidatedConvert(request.pools));
     return Request{
-            .inputs = NN_TRY(unvalidatedConvert(request.inputs)),
-            .outputs = NN_TRY(unvalidatedConvert(request.outputs)),
-            .pools = NN_TRY(unvalidatedConvert(request.pools)),
+            .inputs = std::move(inputs),
+            .outputs = std::move(outputs),
+            .pools = std::move(pools),
     };
 }
 
 GeneralResult<Request::Argument> unvalidatedConvert(const aidl_hal::RequestArgument& argument) {
     const auto lifetime = argument.hasNoValue ? Request::Argument::LifeTime::NO_VALUE
                                               : Request::Argument::LifeTime::POOL;
+    const auto location = NN_TRY(unvalidatedConvert(argument.location));
+    auto dimensions = NN_TRY(toUnsigned(argument.dimensions));
     return Request::Argument{
             .lifetime = lifetime,
-            .location = NN_TRY(unvalidatedConvert(argument.location)),
-            .dimensions = NN_TRY(toUnsigned(argument.dimensions)),
+            .location = location,
+            .dimensions = std::move(dimensions),
     };
 }
 
@@ -498,20 +525,22 @@
     return static_cast<ExecutionPreference>(executionPreference);
 }
 
-GeneralResult<SharedHandle> unvalidatedConvert(const NativeHandle& aidlNativeHandle) {
-    return std::make_shared<const Handle>(NN_TRY(unvalidatedConvertHelper(aidlNativeHandle)));
-}
-
 GeneralResult<std::vector<Operation>> unvalidatedConvert(
         const std::vector<aidl_hal::Operation>& operations) {
     return unvalidatedConvertVec(operations);
 }
 
-GeneralResult<SyncFence> unvalidatedConvert(const ndk::ScopedFileDescriptor& syncFence) {
-    auto duplicatedFd = NN_TRY(dupFd(syncFence.get()));
-    return SyncFence::create(std::move(duplicatedFd));
+GeneralResult<SharedHandle> unvalidatedConvert(const ndk::ScopedFileDescriptor& handle) {
+    auto duplicatedFd = NN_TRY(dupFd(handle.get()));
+    return std::make_shared<const Handle>(std::move(duplicatedFd));
 }
 
+#ifdef NN_AIDL_V4_OR_ABOVE
+GeneralResult<TokenValuePair> unvalidatedConvert(const aidl_hal::TokenValuePair& tokenValuePair) {
+    return TokenValuePair{.token = tokenValuePair.token, .value = tokenValuePair.value};
+}
+#endif  // NN_AIDL_V4_OR_ABOVE
+
 GeneralResult<Capabilities> convert(const aidl_hal::Capabilities& capabilities) {
     return validatedConvert(capabilities);
 }
@@ -553,8 +582,12 @@
     return validatedConvert(timing);
 }
 
-GeneralResult<SyncFence> convert(const ndk::ScopedFileDescriptor& syncFence) {
-    return validatedConvert(syncFence);
+GeneralResult<SharedHandle> convert(const ndk::ScopedFileDescriptor& handle) {
+    return validatedConvert(handle);
+}
+
+GeneralResult<BufferDesc> convert(const aidl_hal::BufferDesc& bufferDesc) {
+    return validatedConvert(bufferDesc);
 }
 
 GeneralResult<std::vector<Extension>> convert(const std::vector<aidl_hal::Extension>& extension) {
@@ -564,12 +597,32 @@
 GeneralResult<std::vector<SharedMemory>> convert(const std::vector<aidl_hal::Memory>& memories) {
     return validatedConvert(memories);
 }
+GeneralResult<std::vector<ExtensionNameAndPrefix>> convert(
+        const std::vector<aidl_hal::ExtensionNameAndPrefix>& extensionNameAndPrefix) {
+    return unvalidatedConvert(extensionNameAndPrefix);
+}
+
+#ifdef NN_AIDL_V4_OR_ABOVE
+GeneralResult<std::vector<TokenValuePair>> convert(
+        const std::vector<aidl_hal::TokenValuePair>& metaData) {
+    return validatedConvert(metaData);
+}
+#endif  // NN_AIDL_V4_OR_ABOVE
 
 GeneralResult<std::vector<OutputShape>> convert(
         const std::vector<aidl_hal::OutputShape>& outputShapes) {
     return validatedConvert(outputShapes);
 }
 
+GeneralResult<std::vector<SharedHandle>> convert(
+        const std::vector<ndk::ScopedFileDescriptor>& handles) {
+    return validatedConvert(handles);
+}
+
+GeneralResult<std::vector<BufferRole>> convert(const std::vector<aidl_hal::BufferRole>& roles) {
+    return validatedConvert(roles);
+}
+
 GeneralResult<std::vector<uint32_t>> toUnsigned(const std::vector<int32_t>& vec) {
     if (!std::all_of(vec.begin(), vec.end(), [](int32_t v) { return v >= 0; })) {
         return NN_ERROR() << "Negative value passed to conversion from signed to unsigned";
@@ -582,53 +635,7 @@
 namespace aidl::android::hardware::neuralnetworks::utils {
 namespace {
 
-template <typename Input>
-using UnvalidatedConvertOutput =
-        std::decay_t<decltype(unvalidatedConvert(std::declval<Input>()).value())>;
-
-template <typename Type>
-nn::GeneralResult<std::vector<UnvalidatedConvertOutput<Type>>> unvalidatedConvertVec(
-        const std::vector<Type>& arguments) {
-    std::vector<UnvalidatedConvertOutput<Type>> halObject;
-    halObject.reserve(arguments.size());
-    for (const auto& argument : arguments) {
-        halObject.push_back(NN_TRY(unvalidatedConvert(argument)));
-    }
-    return halObject;
-}
-
-template <typename Type>
-nn::GeneralResult<std::vector<UnvalidatedConvertOutput<Type>>> unvalidatedConvert(
-        const std::vector<Type>& arguments) {
-    return unvalidatedConvertVec(arguments);
-}
-
-template <typename Type>
-nn::GeneralResult<UnvalidatedConvertOutput<Type>> validatedConvert(const Type& canonical) {
-    NN_TRY(compliantVersion(canonical));
-    return utils::unvalidatedConvert(canonical);
-}
-
-template <typename Type>
-nn::GeneralResult<std::vector<UnvalidatedConvertOutput<Type>>> validatedConvert(
-        const std::vector<Type>& arguments) {
-    std::vector<UnvalidatedConvertOutput<Type>> halObject(arguments.size());
-    for (size_t i = 0; i < arguments.size(); ++i) {
-        halObject[i] = NN_TRY(validatedConvert(arguments[i]));
-    }
-    return halObject;
-}
-
-nn::GeneralResult<common::NativeHandle> unvalidatedConvert(const nn::Handle& handle) {
-    common::NativeHandle aidlNativeHandle;
-    aidlNativeHandle.fds.reserve(handle.fds.size());
-    for (const auto& fd : handle.fds) {
-        auto duplicatedFd = NN_TRY(nn::dupFd(fd.get()));
-        aidlNativeHandle.fds.emplace_back(duplicatedFd.release());
-    }
-    aidlNativeHandle.ints = handle.ints;
-    return aidlNativeHandle;
-}
+using utils::unvalidatedConvert;
 
 // Helper template for std::visit
 template <class... Ts>
@@ -636,8 +643,9 @@
     using Ts::operator()...;
 };
 template <class... Ts>
-overloaded(Ts...)->overloaded<Ts...>;
+overloaded(Ts...) -> overloaded<Ts...>;
 
+#ifdef __ANDROID__
 nn::GeneralResult<common::NativeHandle> aidlHandleFromNativeHandle(
         const native_handle_t& nativeHandle) {
     auto handle = ::android::dupToAidl(&nativeHandle);
@@ -647,6 +655,7 @@
     }
     return handle;
 }
+#endif  // __ANDROID__
 
 nn::GeneralResult<Memory> unvalidatedConvert(const nn::Memory::Ashmem& memory) {
     if constexpr (std::numeric_limits<size_t>::max() > std::numeric_limits<int64_t>::max()) {
@@ -694,6 +703,7 @@
 }
 
 nn::GeneralResult<Memory> unvalidatedConvert(const nn::Memory::HardwareBuffer& memory) {
+#ifdef __ANDROID__
     const native_handle_t* nativeHandle = AHardwareBuffer_getNativeHandle(memory.handle.get());
     if (nativeHandle == nullptr) {
         return (NN_ERROR() << "unvalidatedConvert failed because AHardwareBuffer_getNativeHandle "
@@ -721,6 +731,12 @@
             .handle = std::move(handle),
     };
     return Memory::make<Memory::Tag::hardwareBuffer>(std::move(hardwareBuffer));
+#else   // __ANDROID__
+    LOG(FATAL) << "nn::GeneralResult<Memory> unvalidatedConvert(const nn::Memory::HardwareBuffer& "
+                  "memory): Not Available on Host Build";
+    (void)memory;
+    return (NN_ERROR() << "unvalidatedConvert failed").operator nn::GeneralResult<Memory>();
+#endif  // __ANDROID__
 }
 
 nn::GeneralResult<Memory> unvalidatedConvert(const nn::Memory::Unknown& /*memory*/) {
@@ -729,6 +745,75 @@
             operator nn::GeneralResult<Memory>();
 }
 
+nn::GeneralResult<PerformanceInfo> unvalidatedConvert(
+        const nn::Capabilities::PerformanceInfo& info) {
+    return PerformanceInfo{.execTime = info.execTime, .powerUsage = info.powerUsage};
+}
+
+nn::GeneralResult<OperandPerformance> unvalidatedConvert(
+        const nn::Capabilities::OperandPerformance& operandPerformance) {
+    const auto type = NN_TRY(unvalidatedConvert(operandPerformance.type));
+    const auto info = NN_TRY(unvalidatedConvert(operandPerformance.info));
+    return OperandPerformance{.type = type, .info = info};
+}
+
+nn::GeneralResult<std::vector<OperandPerformance>> unvalidatedConvert(
+        const nn::Capabilities::OperandPerformanceTable& table) {
+    std::vector<OperandPerformance> operandPerformances;
+    operandPerformances.reserve(table.asVector().size());
+    for (const auto& operandPerformance : table.asVector()) {
+        operandPerformances.push_back(NN_TRY(unvalidatedConvert(operandPerformance)));
+    }
+    return operandPerformances;
+}
+
+nn::GeneralResult<ExtensionOperandTypeInformation> unvalidatedConvert(
+        const nn::Extension::OperandTypeInformation& info) {
+    return ExtensionOperandTypeInformation{.type = info.type,
+                                           .isTensor = info.isTensor,
+                                           .byteSize = static_cast<int32_t>(info.byteSize)};
+}
+
+nn::GeneralResult<int64_t> unvalidatedConvert(const nn::Duration& duration) {
+    if (duration < nn::Duration::zero()) {
+        return NN_ERROR() << "Unable to convert invalid (negative) duration";
+    }
+    constexpr std::chrono::nanoseconds::rep kIntMax = std::numeric_limits<int64_t>::max();
+    const auto count = duration.count();
+    return static_cast<int64_t>(std::min(count, kIntMax));
+}
+
+template <typename Input>
+using UnvalidatedConvertOutput =
+        std::decay_t<decltype(unvalidatedConvert(std::declval<Input>()).value())>;
+
+template <typename Type>
+nn::GeneralResult<std::vector<UnvalidatedConvertOutput<Type>>> unvalidatedConvert(
+        const std::vector<Type>& arguments) {
+    std::vector<UnvalidatedConvertOutput<Type>> halObject;
+    halObject.reserve(arguments.size());
+    for (const auto& argument : arguments) {
+        halObject.push_back(NN_TRY(unvalidatedConvert(argument)));
+    }
+    return halObject;
+}
+
+template <typename Type>
+nn::GeneralResult<UnvalidatedConvertOutput<Type>> validatedConvert(const Type& canonical) {
+    NN_TRY(compliantVersion(canonical));
+    return utils::unvalidatedConvert(canonical);
+}
+
+template <typename Type>
+nn::GeneralResult<std::vector<UnvalidatedConvertOutput<Type>>> validatedConvert(
+        const std::vector<Type>& arguments) {
+    std::vector<UnvalidatedConvertOutput<Type>> halObject(arguments.size());
+    for (size_t i = 0; i < arguments.size(); ++i) {
+        halObject[i] = NN_TRY(validatedConvert(arguments[i]));
+    }
+    return halObject;
+}
+
 }  // namespace
 
 nn::GeneralResult<std::vector<uint8_t>> unvalidatedConvert(const nn::CacheToken& cacheToken) {
@@ -736,7 +821,8 @@
 }
 
 nn::GeneralResult<BufferDesc> unvalidatedConvert(const nn::BufferDesc& bufferDesc) {
-    return BufferDesc{.dimensions = NN_TRY(toSigned(bufferDesc.dimensions))};
+    auto dimensions = NN_TRY(toSigned(bufferDesc.dimensions));
+    return BufferDesc{.dimensions = std::move(dimensions)};
 }
 
 nn::GeneralResult<BufferRole> unvalidatedConvert(const nn::BufferRole& bufferRole) {
@@ -751,13 +837,21 @@
     };
 }
 
-nn::GeneralResult<bool> unvalidatedConvert(const nn::MeasureTiming& measureTiming) {
-    return measureTiming == nn::MeasureTiming::YES;
+nn::GeneralResult<DeviceType> unvalidatedConvert(const nn::DeviceType& deviceType) {
+    switch (deviceType) {
+        case nn::DeviceType::UNKNOWN:
+            break;
+        case nn::DeviceType::OTHER:
+        case nn::DeviceType::CPU:
+        case nn::DeviceType::GPU:
+        case nn::DeviceType::ACCELERATOR:
+            return static_cast<DeviceType>(deviceType);
+    }
+    return NN_ERROR() << "Invalid DeviceType " << deviceType;
 }
 
-nn::GeneralResult<common::NativeHandle> unvalidatedConvert(const nn::SharedHandle& sharedHandle) {
-    CHECK(sharedHandle != nullptr);
-    return unvalidatedConvert(*sharedHandle);
+nn::GeneralResult<bool> unvalidatedConvert(const nn::MeasureTiming& measureTiming) {
+    return measureTiming == nn::MeasureTiming::YES;
 }
 
 nn::GeneralResult<Memory> unvalidatedConvert(const nn::SharedMemory& memory) {
@@ -787,7 +881,8 @@
 }
 
 nn::GeneralResult<OutputShape> unvalidatedConvert(const nn::OutputShape& outputShape) {
-    return OutputShape{.dimensions = NN_TRY(toSigned(outputShape.dimensions)),
+    auto dimensions = NN_TRY(toSigned(outputShape.dimensions));
+    return OutputShape{.dimensions = std::move(dimensions),
                        .isSufficient = outputShape.isSufficient};
 }
 
@@ -855,14 +950,19 @@
 }
 
 nn::GeneralResult<Operand> unvalidatedConvert(const nn::Operand& operand) {
+    const auto type = NN_TRY(unvalidatedConvert(operand.type));
+    auto dimensions = NN_TRY(toSigned(operand.dimensions));
+    const auto lifetime = NN_TRY(unvalidatedConvert(operand.lifetime));
+    const auto location = NN_TRY(unvalidatedConvert(operand.location));
+    auto extraParams = NN_TRY(unvalidatedConvert(operand.extraParams));
     return Operand{
-            .type = NN_TRY(unvalidatedConvert(operand.type)),
-            .dimensions = NN_TRY(toSigned(operand.dimensions)),
+            .type = type,
+            .dimensions = std::move(dimensions),
             .scale = operand.scale,
             .zeroPoint = operand.zeroPoint,
-            .lifetime = NN_TRY(unvalidatedConvert(operand.lifetime)),
-            .location = NN_TRY(unvalidatedConvert(operand.location)),
-            .extraParams = NN_TRY(unvalidatedConvert(operand.extraParams)),
+            .lifetime = lifetime,
+            .location = location,
+            .extraParams = std::move(extraParams),
     };
 }
 
@@ -874,19 +974,26 @@
 }
 
 nn::GeneralResult<Operation> unvalidatedConvert(const nn::Operation& operation) {
+    const auto type = NN_TRY(unvalidatedConvert(operation.type));
+    auto inputs = NN_TRY(toSigned(operation.inputs));
+    auto outputs = NN_TRY(toSigned(operation.outputs));
     return Operation{
-            .type = NN_TRY(unvalidatedConvert(operation.type)),
-            .inputs = NN_TRY(toSigned(operation.inputs)),
-            .outputs = NN_TRY(toSigned(operation.outputs)),
+            .type = type,
+            .inputs = std::move(inputs),
+            .outputs = std::move(outputs),
     };
 }
 
 nn::GeneralResult<Subgraph> unvalidatedConvert(const nn::Model::Subgraph& subgraph) {
+    auto operands = NN_TRY(unvalidatedConvert(subgraph.operands));
+    auto operations = NN_TRY(unvalidatedConvert(subgraph.operations));
+    auto inputIndexes = NN_TRY(toSigned(subgraph.inputIndexes));
+    auto outputIndexes = NN_TRY(toSigned(subgraph.outputIndexes));
     return Subgraph{
-            .operands = NN_TRY(unvalidatedConvert(subgraph.operands)),
-            .operations = NN_TRY(unvalidatedConvert(subgraph.operations)),
-            .inputIndexes = NN_TRY(toSigned(subgraph.inputIndexes)),
-            .outputIndexes = NN_TRY(toSigned(subgraph.outputIndexes)),
+            .operands = std::move(operands),
+            .operations = std::move(operations),
+            .inputIndexes = std::move(inputIndexes),
+            .outputIndexes = std::move(outputIndexes),
     };
 }
 
@@ -896,7 +1003,7 @@
 }
 
 nn::GeneralResult<ExtensionNameAndPrefix> unvalidatedConvert(
-        const nn::Model::ExtensionNameAndPrefix& extensionNameToPrefix) {
+        const nn::ExtensionNameAndPrefix& extensionNameToPrefix) {
     return ExtensionNameAndPrefix{
             .name = extensionNameToPrefix.name,
             .prefix = extensionNameToPrefix.prefix,
@@ -904,13 +1011,23 @@
 }
 
 nn::GeneralResult<Model> unvalidatedConvert(const nn::Model& model) {
+    if (!hal::utils::hasNoPointerData(model)) {
+        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
+               << "Model cannot be unvalidatedConverted because it contains pointer-based memory";
+    }
+
+    auto main = NN_TRY(unvalidatedConvert(model.main));
+    auto referenced = NN_TRY(unvalidatedConvert(model.referenced));
+    auto operandValues = NN_TRY(unvalidatedConvert(model.operandValues));
+    auto pools = NN_TRY(unvalidatedConvert(model.pools));
+    auto extensionNameToPrefix = NN_TRY(unvalidatedConvert(model.extensionNameToPrefix));
     return Model{
-            .main = NN_TRY(unvalidatedConvert(model.main)),
-            .referenced = NN_TRY(unvalidatedConvert(model.referenced)),
-            .operandValues = NN_TRY(unvalidatedConvert(model.operandValues)),
-            .pools = NN_TRY(unvalidatedConvert(model.pools)),
+            .main = std::move(main),
+            .referenced = std::move(referenced),
+            .operandValues = std::move(operandValues),
+            .pools = std::move(pools),
             .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
-            .extensionNameToPrefix = NN_TRY(unvalidatedConvert(model.extensionNameToPrefix)),
+            .extensionNameToPrefix = std::move(extensionNameToPrefix),
     };
 }
 
@@ -919,10 +1036,18 @@
 }
 
 nn::GeneralResult<Request> unvalidatedConvert(const nn::Request& request) {
+    if (!hal::utils::hasNoPointerData(request)) {
+        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
+               << "Request cannot be unvalidatedConverted because it contains pointer-based memory";
+    }
+
+    auto inputs = NN_TRY(unvalidatedConvert(request.inputs));
+    auto outputs = NN_TRY(unvalidatedConvert(request.outputs));
+    auto pools = NN_TRY(unvalidatedConvert(request.pools));
     return Request{
-            .inputs = NN_TRY(unvalidatedConvert(request.inputs)),
-            .outputs = NN_TRY(unvalidatedConvert(request.outputs)),
-            .pools = NN_TRY(unvalidatedConvert(request.pools)),
+            .inputs = std::move(inputs),
+            .outputs = std::move(outputs),
+            .pools = std::move(pools),
     };
 }
 
@@ -933,10 +1058,12 @@
                << "Request cannot be unvalidatedConverted because it contains pointer-based memory";
     }
     const bool hasNoValue = requestArgument.lifetime == nn::Request::Argument::LifeTime::NO_VALUE;
+    const auto location = NN_TRY(unvalidatedConvert(requestArgument.location));
+    auto dimensions = NN_TRY(toSigned(requestArgument.dimensions));
     return RequestArgument{
             .hasNoValue = hasNoValue,
-            .location = NN_TRY(unvalidatedConvert(requestArgument.location)),
-            .dimensions = NN_TRY(toSigned(requestArgument.dimensions)),
+            .location = location,
+            .dimensions = std::move(dimensions),
     };
 }
 
@@ -963,21 +1090,14 @@
 }
 
 nn::GeneralResult<Timing> unvalidatedConvert(const nn::Timing& timing) {
+    const auto timeOnDeviceNs = NN_TRY(unvalidatedConvert(timing.timeOnDevice));
+    const auto timeInDriverNs = NN_TRY(unvalidatedConvert(timing.timeInDriver));
     return Timing{
-            .timeOnDeviceNs = NN_TRY(unvalidatedConvert(timing.timeOnDevice)),
-            .timeInDriverNs = NN_TRY(unvalidatedConvert(timing.timeInDriver)),
+            .timeOnDeviceNs = timeOnDeviceNs,
+            .timeInDriverNs = timeInDriverNs,
     };
 }
 
-nn::GeneralResult<int64_t> unvalidatedConvert(const nn::Duration& duration) {
-    if (duration < nn::Duration::zero()) {
-        return NN_ERROR() << "Unable to convert invalid (negative) duration";
-    }
-    constexpr std::chrono::nanoseconds::rep kIntMax = std::numeric_limits<int64_t>::max();
-    const auto count = duration.count();
-    return static_cast<int64_t>(std::min(count, kIntMax));
-}
-
 nn::GeneralResult<int64_t> unvalidatedConvert(const nn::OptionalDuration& optionalDuration) {
     if (!optionalDuration.has_value()) {
         return kNoTiming;
@@ -997,19 +1117,38 @@
     return ndk::ScopedFileDescriptor(duplicatedFd.release());
 }
 
-nn::GeneralResult<ndk::ScopedFileDescriptor> unvalidatedConvertCache(
-        const nn::SharedHandle& handle) {
-    if (handle->ints.size() != 0) {
-        NN_ERROR() << "Cache handle must not contain ints";
-    }
-    if (handle->fds.size() != 1) {
-        NN_ERROR() << "Cache handle must contain exactly one fd but contains "
-                   << handle->fds.size();
-    }
-    auto duplicatedFd = NN_TRY(nn::dupFd(handle->fds.front().get()));
+nn::GeneralResult<ndk::ScopedFileDescriptor> unvalidatedConvert(const nn::SharedHandle& handle) {
+    auto duplicatedFd = NN_TRY(nn::dupFd(handle->get()));
     return ndk::ScopedFileDescriptor(duplicatedFd.release());
 }
 
+nn::GeneralResult<Capabilities> unvalidatedConvert(const nn::Capabilities& capabilities) {
+    const auto relaxedFloat32toFloat16PerformanceTensor =
+            NN_TRY(unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor));
+    const auto relaxedFloat32toFloat16PerformanceScalar =
+            NN_TRY(unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceScalar));
+    auto operandPerformance = NN_TRY(unvalidatedConvert(capabilities.operandPerformance));
+    const auto ifPerformance = NN_TRY(unvalidatedConvert(capabilities.ifPerformance));
+    const auto whilePerformance = NN_TRY(unvalidatedConvert(capabilities.whilePerformance));
+    return Capabilities{
+            .relaxedFloat32toFloat16PerformanceTensor = relaxedFloat32toFloat16PerformanceTensor,
+            .relaxedFloat32toFloat16PerformanceScalar = relaxedFloat32toFloat16PerformanceScalar,
+            .operandPerformance = std::move(operandPerformance),
+            .ifPerformance = ifPerformance,
+            .whilePerformance = whilePerformance,
+    };
+}
+
+nn::GeneralResult<Extension> unvalidatedConvert(const nn::Extension& extension) {
+    auto operandTypes = NN_TRY(unvalidatedConvert(extension.operandTypes));
+    return Extension{.name = extension.name, .operandTypes = std::move(operandTypes)};
+}
+#ifdef NN_AIDL_V4_OR_ABOVE
+nn::GeneralResult<TokenValuePair> unvalidatedConvert(const nn::TokenValuePair& tokenValuePair) {
+    return TokenValuePair{.token = tokenValuePair.token, .value = tokenValuePair.value};
+}
+#endif  // NN_AIDL_V4_OR_ABOVE
+
 nn::GeneralResult<std::vector<uint8_t>> convert(const nn::CacheToken& cacheToken) {
     return validatedConvert(cacheToken);
 }
@@ -1018,6 +1157,10 @@
     return validatedConvert(bufferDesc);
 }
 
+nn::GeneralResult<DeviceType> convert(const nn::DeviceType& deviceType) {
+    return validatedConvert(deviceType);
+}
+
 nn::GeneralResult<bool> convert(const nn::MeasureTiming& measureTiming) {
     return validatedConvert(measureTiming);
 }
@@ -1058,6 +1201,14 @@
     return validatedConvert(outputShapes);
 }
 
+nn::GeneralResult<Capabilities> convert(const nn::Capabilities& capabilities) {
+    return validatedConvert(capabilities);
+}
+
+nn::GeneralResult<Extension> convert(const nn::Extension& extension) {
+    return validatedConvert(extension);
+}
+
 nn::GeneralResult<std::vector<BufferRole>> convert(const std::vector<nn::BufferRole>& bufferRoles) {
     return validatedConvert(bufferRoles);
 }
@@ -1069,22 +1220,28 @@
 
 nn::GeneralResult<std::vector<ndk::ScopedFileDescriptor>> convert(
         const std::vector<nn::SharedHandle>& cacheHandles) {
-    const auto version = NN_TRY(hal::utils::makeGeneralFailure(nn::validate(cacheHandles)));
-    if (version > kVersion) {
-        return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion;
-    }
-    std::vector<ndk::ScopedFileDescriptor> cacheFds;
-    cacheFds.reserve(cacheHandles.size());
-    for (const auto& cacheHandle : cacheHandles) {
-        cacheFds.push_back(NN_TRY(unvalidatedConvertCache(cacheHandle)));
-    }
-    return cacheFds;
+    return validatedConvert(cacheHandles);
 }
 
 nn::GeneralResult<std::vector<ndk::ScopedFileDescriptor>> convert(
         const std::vector<nn::SyncFence>& syncFences) {
     return validatedConvert(syncFences);
 }
+nn::GeneralResult<std::vector<ExtensionNameAndPrefix>> convert(
+        const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) {
+    return unvalidatedConvert(extensionNameToPrefix);
+}
+
+#ifdef NN_AIDL_V4_OR_ABOVE
+nn::GeneralResult<std::vector<TokenValuePair>> convert(
+        const std::vector<nn::TokenValuePair>& metaData) {
+    return validatedConvert(metaData);
+}
+#endif  // NN_AIDL_V4_OR_ABOVE
+
+nn::GeneralResult<std::vector<Extension>> convert(const std::vector<nn::Extension>& extensions) {
+    return validatedConvert(extensions);
+}
 
 nn::GeneralResult<std::vector<int32_t>> toSigned(const std::vector<uint32_t>& vec) {
     if (!std::all_of(vec.begin(), vec.end(),
@@ -1094,4 +1251,8 @@
     return std::vector<int32_t>(vec.begin(), vec.end());
 }
 
+std::vector<uint8_t> toVec(const std::array<uint8_t, IDevice::BYTE_SIZE_OF_CACHE_TOKEN>& token) {
+    return std::vector<uint8_t>(token.begin(), token.end());
+}
+
 }  // namespace aidl::android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/aidl/utils/src/Device.cpp b/neuralnetworks/aidl/utils/src/Device.cpp
index e80de0b..b64a40d 100644
--- a/neuralnetworks/aidl/utils/src/Device.cpp
+++ b/neuralnetworks/aidl/utils/src/Device.cpp
@@ -125,7 +125,7 @@
 }  // namespace
 
 nn::GeneralResult<std::shared_ptr<const Device>> Device::create(
-        std::string name, std::shared_ptr<aidl_hal::IDevice> device) {
+        std::string name, std::shared_ptr<aidl_hal::IDevice> device, nn::Version featureLevel) {
     if (name.empty()) {
         return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
                << "aidl_hal::utils::Device::create must have non-empty name";
@@ -143,18 +143,19 @@
 
     auto deathHandler = NN_TRY(DeathHandler::create(device));
     return std::make_shared<const Device>(
-            PrivateConstructorTag{}, std::move(name), std::move(versionString), deviceType,
-            std::move(extensions), std::move(capabilities), numberOfCacheFilesNeeded,
+            PrivateConstructorTag{}, std::move(name), std::move(versionString), featureLevel,
+            deviceType, std::move(extensions), std::move(capabilities), numberOfCacheFilesNeeded,
             std::move(device), std::move(deathHandler));
 }
 
 Device::Device(PrivateConstructorTag /*tag*/, std::string name, std::string versionString,
-               nn::DeviceType deviceType, std::vector<nn::Extension> extensions,
-               nn::Capabilities capabilities,
+               nn::Version featureLevel, nn::DeviceType deviceType,
+               std::vector<nn::Extension> extensions, nn::Capabilities capabilities,
                std::pair<uint32_t, uint32_t> numberOfCacheFilesNeeded,
                std::shared_ptr<aidl_hal::IDevice> device, DeathHandler deathHandler)
     : kName(std::move(name)),
       kVersionString(std::move(versionString)),
+      kFeatureLevel(featureLevel),
       kDeviceType(deviceType),
       kExtensions(std::move(extensions)),
       kCapabilities(std::move(capabilities)),
@@ -171,7 +172,7 @@
 }
 
 nn::Version Device::getFeatureLevel() const {
-    return nn::Version::ANDROID_S;
+    return kFeatureLevel;
 }
 
 nn::DeviceType Device::getType() const {
@@ -214,7 +215,9 @@
 nn::GeneralResult<nn::SharedPreparedModel> Device::prepareModel(
         const nn::Model& model, nn::ExecutionPreference preference, nn::Priority priority,
         nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
-        const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token) const {
+        const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token,
+        const std::vector<nn::TokenValuePair>& hints,
+        const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const {
     // Ensure that model is ready for IPC.
     std::optional<nn::Model> maybeModelInShared;
     const nn::Model& modelInShared =
@@ -224,17 +227,28 @@
     const auto aidlPreference = NN_TRY(convert(preference));
     const auto aidlPriority = NN_TRY(convert(priority));
     const auto aidlDeadline = NN_TRY(convert(deadline));
-    const auto aidlModelCache = NN_TRY(convert(modelCache));
-    const auto aidlDataCache = NN_TRY(convert(dataCache));
-    const auto aidlToken = NN_TRY(convert(token));
+    auto aidlModelCache = NN_TRY(convert(modelCache));
+    auto aidlDataCache = NN_TRY(convert(dataCache));
 
-    const auto cb = ndk::SharedRefBase::make<PreparedModelCallback>();
+    const auto cb = ndk::SharedRefBase::make<PreparedModelCallback>(kFeatureLevel);
     const auto scoped = kDeathHandler.protectCallback(cb.get());
 
+    if (kFeatureLevel.level >= nn::Version::Level::FEATURE_LEVEL_8) {
+        auto aidlHints = NN_TRY(convert(hints));
+        auto aidlExtensionPrefix = NN_TRY(convert(extensionNameToPrefix));
+        const auto ret = kDevice->prepareModelWithConfig(
+                aidlModel,
+                {aidlPreference, aidlPriority, aidlDeadline, std::move(aidlModelCache),
+                 std::move(aidlDataCache), token, std::move(aidlHints),
+                 std::move(aidlExtensionPrefix)},
+                cb);
+        HANDLE_ASTATUS(ret) << "prepareModel failed";
+        return cb->get();
+    }
+    const auto aidlToken = NN_TRY(convert(token));
     const auto ret = kDevice->prepareModel(aidlModel, aidlPreference, aidlPriority, aidlDeadline,
                                            aidlModelCache, aidlDataCache, aidlToken, cb);
     HANDLE_ASTATUS(ret) << "prepareModel failed";
-
     return cb->get();
 }
 
@@ -246,7 +260,7 @@
     const auto aidlDataCache = NN_TRY(convert(dataCache));
     const auto aidlToken = NN_TRY(convert(token));
 
-    const auto cb = ndk::SharedRefBase::make<PreparedModelCallback>();
+    const auto cb = ndk::SharedRefBase::make<PreparedModelCallback>(kFeatureLevel);
     const auto scoped = kDeathHandler.protectCallback(cb.get());
 
     const auto ret = kDevice->prepareModelFromCache(aidlDeadline, aidlModelCache, aidlDataCache,
diff --git a/neuralnetworks/aidl/utils/src/Execution.cpp b/neuralnetworks/aidl/utils/src/Execution.cpp
index 2aee8a6..2fd88af 100644
--- a/neuralnetworks/aidl/utils/src/Execution.cpp
+++ b/neuralnetworks/aidl/utils/src/Execution.cpp
@@ -25,7 +25,6 @@
 #include <nnapi/Result.h>
 #include <nnapi/Types.h>
 #include <nnapi/hal/CommonUtils.h>
-#include <nnapi/hal/HandleError.h>
 
 #include <memory>
 #include <utility>
@@ -36,44 +35,61 @@
 
 namespace aidl::android::hardware::neuralnetworks::utils {
 
-nn::GeneralResult<std::shared_ptr<const Execution>> Execution::create(
-        std::shared_ptr<const PreparedModel> preparedModel, Request request,
-        hal::utils::RequestRelocation relocation, bool measure, int64_t loopTimeoutDuration) {
+nn::GeneralResult<std::shared_ptr<const ExecutionWithCachedRequest>>
+ExecutionWithCachedRequest::create(std::shared_ptr<const PreparedModel> preparedModel,
+                                   Request request, hal::utils::RequestRelocation relocation,
+                                   bool measure, int64_t loopTimeoutDuration) {
     if (preparedModel == nullptr) {
-        return NN_ERROR() << "aidl::utils::Execution::create must have non-null preparedModel";
+        return NN_ERROR() << "aidl::utils::ExecutionWithCachedRequest::create must have non-null "
+                             "preparedModel";
     }
 
-    return std::make_shared<const Execution>(PrivateConstructorTag{}, std::move(preparedModel),
-                                             std::move(request), std::move(relocation), measure,
-                                             loopTimeoutDuration);
+    return std::make_shared<const ExecutionWithCachedRequest>(
+            PrivateConstructorTag{}, std::move(preparedModel), std::move(request),
+            std::move(relocation), measure, loopTimeoutDuration);
 }
 
-Execution::Execution(PrivateConstructorTag /*tag*/,
-                     std::shared_ptr<const PreparedModel> preparedModel, Request request,
-                     hal::utils::RequestRelocation relocation, bool measure,
-                     int64_t loopTimeoutDuration)
+ExecutionWithCachedRequest::ExecutionWithCachedRequest(
+        PrivateConstructorTag /*tag*/, std::shared_ptr<const PreparedModel> preparedModel,
+        Request request, hal::utils::RequestRelocation relocation, bool measure,
+        int64_t loopTimeoutDuration)
     : kPreparedModel(std::move(preparedModel)),
       kRequest(std::move(request)),
       kRelocation(std::move(relocation)),
       kMeasure(measure),
       kLoopTimeoutDuration(loopTimeoutDuration) {}
 
-nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> Execution::compute(
-        const nn::OptionalTimePoint& deadline) const {
-    const auto aidlDeadline = NN_TRY(hal::utils::makeExecutionFailure(convert(deadline)));
+nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>
+ExecutionWithCachedRequest::compute(const nn::OptionalTimePoint& deadline) const {
+    const auto aidlDeadline = NN_TRY(convert(deadline));
     return kPreparedModel->executeInternal(kRequest, kMeasure, aidlDeadline, kLoopTimeoutDuration,
-                                           kRelocation);
+                                           {}, {}, kRelocation);
 }
 
-nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>> Execution::computeFenced(
+nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>>
+ExecutionWithCachedRequest::computeFenced(
         const std::vector<nn::SyncFence>& waitFor, const nn::OptionalTimePoint& deadline,
         const nn::OptionalDuration& timeoutDurationAfterFence) const {
     const auto aidlWaitFor = NN_TRY(convert(waitFor));
     const auto aidlDeadline = NN_TRY(convert(deadline));
     const auto aidlTimeoutDurationAfterFence = NN_TRY(convert(timeoutDurationAfterFence));
-    return kPreparedModel->executeFencedInternal(kRequest, aidlWaitFor, kMeasure, aidlDeadline,
-                                                 kLoopTimeoutDuration,
-                                                 aidlTimeoutDurationAfterFence, kRelocation);
+    return kPreparedModel->executeFencedInternal(
+            kRequest, aidlWaitFor, kMeasure, aidlDeadline, kLoopTimeoutDuration,
+            aidlTimeoutDurationAfterFence, {}, {}, kRelocation);
 }
 
+nn::GeneralResult<std::shared_ptr<const Execution>> Execution::create(
+        std::shared_ptr<aidl_hal::IExecution> execution, hal::utils::RequestRelocation relocation) {
+    if (execution == nullptr) {
+        return NN_ERROR() << "aidl::utils::Execution::create must have non-null execution";
+    }
+
+    return std::make_shared<const Execution>(PrivateConstructorTag{}, std::move(execution),
+                                             std::move(relocation));
+}
+
+Execution::Execution(PrivateConstructorTag /*tag*/, std::shared_ptr<aidl_hal::IExecution> execution,
+                     hal::utils::RequestRelocation relocation)
+    : kExecution(std::move(execution)), kRelocation(std::move(relocation)) {}
+
 }  // namespace aidl::android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/aidl/utils/src/HalUtils.cpp b/neuralnetworks/aidl/utils/src/HalUtils.cpp
new file mode 100644
index 0000000..64b6259
--- /dev/null
+++ b/neuralnetworks/aidl/utils/src/HalUtils.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+// This file contains pre-canonical-types utility code and includes HAL
+// utilities. LegacyUtils.h is the subset of these utilities that do not touch
+// HAL.
+
+#include "HalUtils.h"
+
+#include "HalInterfaces.h"
+
+#include <android-base/logging.h>
+#include <nnapi/TypeUtils.h>
+#include <nnapi/hal/aidl/Conversions.h>
+
+#include <algorithm>
+#include <iterator>
+#include <type_traits>
+#include <vector>
+
+namespace android::nn {
+
+std::vector<aidl_hal::OperandPerformance> nonExtensionOperandPerformance(
+        aidl_hal::PerformanceInfo perf) {
+    static constexpr ndk::enum_range<aidl_hal::OperandType> kOperandTypeRange;
+    std::vector<aidl_hal::OperandPerformance> ret;
+    ret.reserve(std::distance(kOperandTypeRange.begin(), kOperandTypeRange.end()));
+    for (aidl_hal::OperandType type : kOperandTypeRange) {
+        if (type != aidl_hal::OperandType::SUBGRAPH) {
+            ret.push_back(aidl_hal::OperandPerformance{type, perf});
+        }
+    }
+    std::sort(ret.begin(), ret.end(),
+              [](const aidl_hal::OperandPerformance& a, const aidl_hal::OperandPerformance& b) {
+                  return a.type < b.type;
+              });
+
+    return ret;
+}
+
+void update(std::vector<aidl_hal::OperandPerformance>* operandPerformance,
+            aidl_hal::OperandType type, aidl_hal::PerformanceInfo perf) {
+    CHECK(operandPerformance != nullptr);
+    const auto it = std::lower_bound(operandPerformance->begin(), operandPerformance->end(), type,
+                                     [](const aidl_hal::OperandPerformance& perf,
+                                        aidl_hal::OperandType type) { return perf.type < type; });
+    CHECK(it != operandPerformance->end())
+            << toString(type) << " not in operand performance vector";
+    it->info = perf;
+}
+
+bool isExtensionOperandType(aidl_hal::OperandType type) {
+    return isExtension(convert(type).value());
+}
+
+bool isNonExtensionScalar(aidl_hal::OperandType type) {
+    return isNonExtensionScalar(convert(type).value());
+}
+
+}  // namespace android::nn
diff --git a/neuralnetworks/aidl/utils/src/InvalidDevice.cpp b/neuralnetworks/aidl/utils/src/InvalidDevice.cpp
index c9d9955..44f8ea9 100644
--- a/neuralnetworks/aidl/utils/src/InvalidDevice.cpp
+++ b/neuralnetworks/aidl/utils/src/InvalidDevice.cpp
@@ -167,6 +167,32 @@
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus InvalidDevice::prepareModelWithConfig(
+        const Model& model, const PrepareModelConfig& config,
+        const std::shared_ptr<IPreparedModelCallback>& callback) {
+    if (!utils::valid(config.extensionNameToPrefix)) {
+        callback->notify(ErrorStatus::INVALID_ARGUMENT, nullptr);
+        return toAStatus(ErrorStatus::INVALID_ARGUMENT, "Invalid extensionNameToPrefix");
+    }
+    for (const auto& hint : config.compilationHints) {
+        auto result = std::find_if(config.extensionNameToPrefix.begin(),
+                                   config.extensionNameToPrefix.end(),
+                                   [&hint](const ExtensionNameAndPrefix& extension) {
+                                       uint16_t prefix = static_cast<uint32_t>(hint.token) >>
+                                                         IDevice::EXTENSION_TYPE_LOW_BITS_TYPE;
+                                       return prefix == extension.prefix;
+                                   });
+        if (result == config.extensionNameToPrefix.end()) {
+            callback->notify(ErrorStatus::INVALID_ARGUMENT, nullptr);
+            return toAStatus(ErrorStatus::INVALID_ARGUMENT,
+                             "Invalid token for compilation hints: " + std::to_string(hint.token));
+        }
+    }
+    return prepareModel(model, config.preference, config.priority, config.deadlineNs,
+                        config.modelCache, config.dataCache, utils::toVec(config.cacheToken),
+                        callback);
+}
+
 ndk::ScopedAStatus InvalidDevice::prepareModelFromCache(
         int64_t /*deadline*/, const std::vector<ndk::ScopedFileDescriptor>& /*modelCache*/,
         const std::vector<ndk::ScopedFileDescriptor>& /*dataCache*/,
diff --git a/neuralnetworks/aidl/utils/src/PreparedModel.cpp b/neuralnetworks/aidl/utils/src/PreparedModel.cpp
index 18e7636..7e3a31c 100644
--- a/neuralnetworks/aidl/utils/src/PreparedModel.cpp
+++ b/neuralnetworks/aidl/utils/src/PreparedModel.cpp
@@ -30,7 +30,6 @@
 #include <nnapi/TypeUtils.h>
 #include <nnapi/Types.h>
 #include <nnapi/hal/CommonUtils.h>
-#include <nnapi/hal/HandleError.h>
 
 #include <memory>
 #include <tuple>
@@ -51,67 +50,20 @@
 nn::GeneralResult<std::pair<nn::Timing, nn::Timing>> convertFencedExecutionResults(
         ErrorStatus status, const aidl_hal::Timing& timingLaunched,
         const aidl_hal::Timing& timingFenced) {
-    HANDLE_HAL_STATUS(status) << "fenced execution callback info failed with " << toString(status);
+    HANDLE_STATUS_AIDL(status) << "fenced execution callback info failed with " << toString(status);
     return std::make_pair(NN_TRY(nn::convert(timingLaunched)), NN_TRY(nn::convert(timingFenced)));
 }
 
-}  // namespace
-
-nn::GeneralResult<std::shared_ptr<const PreparedModel>> PreparedModel::create(
-        std::shared_ptr<aidl_hal::IPreparedModel> preparedModel) {
-    if (preparedModel == nullptr) {
-        return NN_ERROR()
-               << "aidl_hal::utils::PreparedModel::create must have non-null preparedModel";
-    }
-
-    return std::make_shared<const PreparedModel>(PrivateConstructorTag{}, std::move(preparedModel));
-}
-
-PreparedModel::PreparedModel(PrivateConstructorTag /*tag*/,
-                             std::shared_ptr<aidl_hal::IPreparedModel> preparedModel)
-    : kPreparedModel(std::move(preparedModel)) {}
-
-nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> PreparedModel::execute(
-        const nn::Request& request, nn::MeasureTiming measure,
-        const nn::OptionalTimePoint& deadline,
-        const nn::OptionalDuration& loopTimeoutDuration) const {
-    // Ensure that request is ready for IPC.
-    std::optional<nn::Request> maybeRequestInShared;
-    hal::utils::RequestRelocation relocation;
-    const nn::Request& requestInShared =
-            NN_TRY(hal::utils::makeExecutionFailure(hal::utils::convertRequestFromPointerToShared(
-                    &request, nn::kDefaultRequestMemoryAlignment, nn::kDefaultRequestMemoryPadding,
-                    &maybeRequestInShared, &relocation)));
-
-    const auto aidlRequest = NN_TRY(hal::utils::makeExecutionFailure(convert(requestInShared)));
-    const auto aidlMeasure = NN_TRY(hal::utils::makeExecutionFailure(convert(measure)));
-    const auto aidlDeadline = NN_TRY(hal::utils::makeExecutionFailure(convert(deadline)));
-    const auto aidlLoopTimeoutDuration =
-            NN_TRY(hal::utils::makeExecutionFailure(convert(loopTimeoutDuration)));
-    return executeInternal(aidlRequest, aidlMeasure, aidlDeadline, aidlLoopTimeoutDuration,
-                           relocation);
-}
-
-nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>
-PreparedModel::executeInternal(const Request& request, bool measure, int64_t deadline,
-                               int64_t loopTimeoutDuration,
-                               const hal::utils::RequestRelocation& relocation) const {
-    if (relocation.input) {
-        relocation.input->flush();
-    }
-
-    ExecutionResult executionResult;
-    const auto ret = kPreparedModel->executeSynchronously(request, measure, deadline,
-                                                          loopTimeoutDuration, &executionResult);
-    HANDLE_ASTATUS(ret) << "executeSynchronously failed";
-    if (!executionResult.outputSufficientSize) {
+nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> handleExecutionResult(
+        const ExecutionResult& result, const hal::utils::RequestRelocation& relocation) {
+    if (!result.outputSufficientSize) {
         auto canonicalOutputShapes =
-                nn::convert(executionResult.outputShapes).value_or(std::vector<nn::OutputShape>{});
+                nn::convert(result.outputShapes).value_or(std::vector<nn::OutputShape>{});
         return NN_ERROR(nn::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE, std::move(canonicalOutputShapes))
                << "execution failed with " << nn::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE;
     }
-    auto [outputShapes, timing] = NN_TRY(hal::utils::makeExecutionFailure(
-            convertExecutionResults(executionResult.outputShapes, executionResult.timing)));
+    auto [outputShapes, timing] =
+            NN_TRY(convertExecutionResults(result.outputShapes, result.timing));
 
     if (relocation.output) {
         relocation.output->flush();
@@ -120,47 +72,11 @@
 }
 
 nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>>
-PreparedModel::executeFenced(const nn::Request& request, const std::vector<nn::SyncFence>& waitFor,
-                             nn::MeasureTiming measure, const nn::OptionalTimePoint& deadline,
-                             const nn::OptionalDuration& loopTimeoutDuration,
-                             const nn::OptionalDuration& timeoutDurationAfterFence) const {
-    // Ensure that request is ready for IPC.
-    std::optional<nn::Request> maybeRequestInShared;
-    hal::utils::RequestRelocation relocation;
-    const nn::Request& requestInShared = NN_TRY(hal::utils::convertRequestFromPointerToShared(
-            &request, nn::kDefaultRequestMemoryAlignment, nn::kDefaultRequestMemoryPadding,
-            &maybeRequestInShared, &relocation));
-
-    const auto aidlRequest = NN_TRY(convert(requestInShared));
-    const auto aidlWaitFor = NN_TRY(convert(waitFor));
-    const auto aidlMeasure = NN_TRY(convert(measure));
-    const auto aidlDeadline = NN_TRY(convert(deadline));
-    const auto aidlLoopTimeoutDuration = NN_TRY(convert(loopTimeoutDuration));
-    const auto aidlTimeoutDurationAfterFence = NN_TRY(convert(timeoutDurationAfterFence));
-    return executeFencedInternal(aidlRequest, aidlWaitFor, aidlMeasure, aidlDeadline,
-                                 aidlLoopTimeoutDuration, aidlTimeoutDurationAfterFence,
-                                 relocation);
-}
-
-nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>>
-PreparedModel::executeFencedInternal(const Request& request,
-                                     const std::vector<ndk::ScopedFileDescriptor>& waitFor,
-                                     bool measure, int64_t deadline, int64_t loopTimeoutDuration,
-                                     int64_t timeoutDurationAfterFence,
-                                     const hal::utils::RequestRelocation& relocation) const {
-    if (relocation.input) {
-        relocation.input->flush();
-    }
-
-    FencedExecutionResult result;
-    const auto ret =
-            kPreparedModel->executeFenced(request, waitFor, measure, deadline, loopTimeoutDuration,
-                                          timeoutDurationAfterFence, &result);
-    HANDLE_ASTATUS(ret) << "executeFenced failed";
-
+handleFencedExecutionResult(const FencedExecutionResult& result,
+                            const hal::utils::RequestRelocation& relocation) {
     auto resultSyncFence = nn::SyncFence::createAsSignaled();
     if (result.syncFence.get() != -1) {
-        resultSyncFence = NN_TRY(nn::convert(result.syncFence));
+        resultSyncFence = nn::SyncFence::create(NN_TRY(nn::convert(result.syncFence))).value();
     }
 
     auto callback = result.callback;
@@ -168,7 +84,7 @@
         return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "callback is null";
     }
 
-    // If executeFenced required the request memory to be moved into shared memory, block here until
+    // If computeFenced required the request memory to be moved into shared memory, block here until
     // the fenced execution has completed and flush the memory back.
     if (relocation.output) {
         const auto state = resultSyncFence.syncWait({});
@@ -192,9 +108,133 @@
     return std::make_pair(std::move(resultSyncFence), std::move(resultCallback));
 }
 
+}  // namespace
+
+nn::GeneralResult<std::shared_ptr<const PreparedModel>> PreparedModel::create(
+        std::shared_ptr<aidl_hal::IPreparedModel> preparedModel, nn::Version featureLevel) {
+    if (preparedModel == nullptr) {
+        return NN_ERROR()
+               << "aidl_hal::utils::PreparedModel::create must have non-null preparedModel";
+    }
+
+    return std::make_shared<const PreparedModel>(PrivateConstructorTag{}, std::move(preparedModel),
+                                                 featureLevel);
+}
+
+PreparedModel::PreparedModel(PrivateConstructorTag /*tag*/,
+                             std::shared_ptr<aidl_hal::IPreparedModel> preparedModel,
+                             nn::Version featureLevel)
+    : kPreparedModel(std::move(preparedModel)), kFeatureLevel(featureLevel) {}
+
+nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> PreparedModel::execute(
+        const nn::Request& request, nn::MeasureTiming measure,
+        const nn::OptionalTimePoint& deadline, const nn::OptionalDuration& loopTimeoutDuration,
+        const std::vector<nn::TokenValuePair>& hints,
+        const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const {
+    // Ensure that request is ready for IPC.
+    std::optional<nn::Request> maybeRequestInShared;
+    hal::utils::RequestRelocation relocation;
+    const nn::Request& requestInShared = NN_TRY(hal::utils::convertRequestFromPointerToShared(
+            &request, nn::kDefaultRequestMemoryAlignment, nn::kDefaultRequestMemoryPadding,
+            &maybeRequestInShared, &relocation));
+
+    const auto aidlRequest = NN_TRY(convert(requestInShared));
+    const auto aidlMeasure = NN_TRY(convert(measure));
+    const auto aidlDeadline = NN_TRY(convert(deadline));
+    const auto aidlLoopTimeoutDuration = NN_TRY(convert(loopTimeoutDuration));
+    return executeInternal(aidlRequest, aidlMeasure, aidlDeadline, aidlLoopTimeoutDuration, hints,
+                           extensionNameToPrefix, relocation);
+}
+
+nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>
+PreparedModel::executeInternal(const Request& request, bool measure, int64_t deadline,
+                               int64_t loopTimeoutDuration,
+                               const std::vector<nn::TokenValuePair>& hints,
+                               const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix,
+                               const hal::utils::RequestRelocation& relocation) const {
+    if (relocation.input) {
+        relocation.input->flush();
+    }
+
+    ExecutionResult executionResult;
+    if (kFeatureLevel.level >= nn::Version::Level::FEATURE_LEVEL_8) {
+        auto aidlHints = NN_TRY(convert(hints));
+        auto aidlExtensionPrefix = NN_TRY(convert(extensionNameToPrefix));
+        const auto ret = kPreparedModel->executeSynchronouslyWithConfig(
+                request,
+                {measure, loopTimeoutDuration, std::move(aidlHints),
+                 std::move(aidlExtensionPrefix)},
+                deadline, &executionResult);
+        HANDLE_ASTATUS(ret) << "executeSynchronouslyWithConfig failed";
+    } else {
+        const auto ret = kPreparedModel->executeSynchronously(
+                request, measure, deadline, loopTimeoutDuration, &executionResult);
+        HANDLE_ASTATUS(ret) << "executeSynchronously failed";
+    }
+    return handleExecutionResult(executionResult, relocation);
+}
+
+nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>>
+PreparedModel::executeFenced(
+        const nn::Request& request, const std::vector<nn::SyncFence>& waitFor,
+        nn::MeasureTiming measure, const nn::OptionalTimePoint& deadline,
+        const nn::OptionalDuration& loopTimeoutDuration,
+        const nn::OptionalDuration& timeoutDurationAfterFence,
+        const std::vector<nn::TokenValuePair>& hints,
+        const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const {
+    // Ensure that request is ready for IPC.
+    std::optional<nn::Request> maybeRequestInShared;
+    hal::utils::RequestRelocation relocation;
+    const nn::Request& requestInShared = NN_TRY(hal::utils::convertRequestFromPointerToShared(
+            &request, nn::kDefaultRequestMemoryAlignment, nn::kDefaultRequestMemoryPadding,
+            &maybeRequestInShared, &relocation));
+
+    const auto aidlRequest = NN_TRY(convert(requestInShared));
+    const auto aidlWaitFor = NN_TRY(convert(waitFor));
+    const auto aidlMeasure = NN_TRY(convert(measure));
+    const auto aidlDeadline = NN_TRY(convert(deadline));
+    const auto aidlLoopTimeoutDuration = NN_TRY(convert(loopTimeoutDuration));
+    const auto aidlTimeoutDurationAfterFence = NN_TRY(convert(timeoutDurationAfterFence));
+    return executeFencedInternal(aidlRequest, aidlWaitFor, aidlMeasure, aidlDeadline,
+                                 aidlLoopTimeoutDuration, aidlTimeoutDurationAfterFence, hints,
+                                 extensionNameToPrefix, relocation);
+}
+
+nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>>
+PreparedModel::executeFencedInternal(
+        const Request& request, const std::vector<ndk::ScopedFileDescriptor>& waitFor, bool measure,
+        int64_t deadline, int64_t loopTimeoutDuration, int64_t timeoutDurationAfterFence,
+        const std::vector<nn::TokenValuePair>& hints,
+        const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix,
+        const hal::utils::RequestRelocation& relocation) const {
+    if (relocation.input) {
+        relocation.input->flush();
+    }
+
+    FencedExecutionResult result;
+    if (kFeatureLevel.level >= nn::Version::Level::FEATURE_LEVEL_8) {
+        auto aidlHints = NN_TRY(convert(hints));
+        auto aidlExtensionPrefix = NN_TRY(convert(extensionNameToPrefix));
+        const auto ret = kPreparedModel->executeFencedWithConfig(
+                request, waitFor,
+                {measure, loopTimeoutDuration, std::move(aidlHints),
+                 std::move(aidlExtensionPrefix)},
+                deadline, timeoutDurationAfterFence, &result);
+        HANDLE_ASTATUS(ret) << "executeFencedWithConfig failed";
+    } else {
+        const auto ret = kPreparedModel->executeFenced(request, waitFor, measure, deadline,
+                                                       loopTimeoutDuration,
+                                                       timeoutDurationAfterFence, &result);
+        HANDLE_ASTATUS(ret) << "executeFenced failed";
+    }
+    return handleFencedExecutionResult(result, relocation);
+}
+
 nn::GeneralResult<nn::SharedExecution> PreparedModel::createReusableExecution(
         const nn::Request& request, nn::MeasureTiming measure,
-        const nn::OptionalDuration& loopTimeoutDuration) const {
+        const nn::OptionalDuration& loopTimeoutDuration,
+        const std::vector<nn::TokenValuePair>& hints,
+        const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const {
     // Ensure that request is ready for IPC.
     std::optional<nn::Request> maybeRequestInShared;
     hal::utils::RequestRelocation relocation;
@@ -205,15 +245,31 @@
     auto aidlRequest = NN_TRY(convert(requestInShared));
     auto aidlMeasure = NN_TRY(convert(measure));
     auto aidlLoopTimeoutDuration = NN_TRY(convert(loopTimeoutDuration));
-    return Execution::create(shared_from_this(), std::move(aidlRequest), std::move(relocation),
-                             aidlMeasure, aidlLoopTimeoutDuration);
+
+    if (kFeatureLevel.level >= nn::Version::Level::FEATURE_LEVEL_8) {
+        std::shared_ptr<IExecution> execution;
+        auto aidlHints = NN_TRY(convert(hints));
+        auto aidlExtensionPrefix = NN_TRY(convert(extensionNameToPrefix));
+
+        const auto ret = kPreparedModel->createReusableExecution(
+                aidlRequest,
+                {aidlMeasure, aidlLoopTimeoutDuration, std::move(aidlHints),
+                 std::move(aidlExtensionPrefix)},
+                &execution);
+        HANDLE_ASTATUS(ret) << "createReusableExecution failed";
+        return Execution::create(std::move(execution), std::move(relocation));
+    }
+
+    return ExecutionWithCachedRequest::create(shared_from_this(), std::move(aidlRequest),
+                                              std::move(relocation), aidlMeasure,
+                                              aidlLoopTimeoutDuration);
 }
 
 nn::GeneralResult<nn::SharedBurst> PreparedModel::configureExecutionBurst() const {
     std::shared_ptr<IBurst> burst;
     const auto ret = kPreparedModel->configureExecutionBurst(&burst);
     HANDLE_ASTATUS(ret) << "configureExecutionBurst failed";
-    return Burst::create(std::move(burst));
+    return Burst::create(std::move(burst), kFeatureLevel);
 }
 
 std::any PreparedModel::getUnderlyingResource() const {
@@ -221,4 +277,36 @@
     return resource;
 }
 
+nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> Execution::compute(
+        const nn::OptionalTimePoint& deadline) const {
+    const auto aidlDeadline = NN_TRY(convert(deadline));
+
+    if (kRelocation.input) {
+        kRelocation.input->flush();
+    }
+
+    ExecutionResult executionResult;
+    auto ret = kExecution->executeSynchronously(aidlDeadline, &executionResult);
+    HANDLE_ASTATUS(ret) << "executeSynchronously failed";
+    return handleExecutionResult(executionResult, kRelocation);
+}
+
+nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>> Execution::computeFenced(
+        const std::vector<nn::SyncFence>& waitFor, const nn::OptionalTimePoint& deadline,
+        const nn::OptionalDuration& timeoutDurationAfterFence) const {
+    const auto aidlWaitFor = NN_TRY(convert(waitFor));
+    const auto aidlDeadline = NN_TRY(convert(deadline));
+    const auto aidlTimeoutDurationAfterFence = NN_TRY(convert(timeoutDurationAfterFence));
+
+    if (kRelocation.input) {
+        kRelocation.input->flush();
+    }
+
+    FencedExecutionResult result;
+    const auto ret = kExecution->executeFenced(aidlWaitFor, aidlDeadline,
+                                               aidlTimeoutDurationAfterFence, &result);
+    HANDLE_ASTATUS(ret) << "executeFenced failed";
+    return handleFencedExecutionResult(result, kRelocation);
+}
+
 }  // namespace aidl::android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/aidl/utils/src/ProtectCallback.cpp b/neuralnetworks/aidl/utils/src/ProtectCallback.cpp
index 124641c..54a673c 100644
--- a/neuralnetworks/aidl/utils/src/ProtectCallback.cpp
+++ b/neuralnetworks/aidl/utils/src/ProtectCallback.cpp
@@ -22,7 +22,6 @@
 #include <android/binder_auto_utils.h>
 #include <android/binder_interface_utils.h>
 #include <nnapi/Result.h>
-#include <nnapi/hal/ProtectCallback.h>
 
 #include <algorithm>
 #include <functional>
@@ -37,7 +36,7 @@
 void DeathMonitor::serviceDied() {
     std::lock_guard guard(mMutex);
     std::for_each(mObjects.begin(), mObjects.end(),
-                  [](hal::utils::IProtectedCallback* killable) { killable->notifyAsDeadObject(); });
+                  [](IProtectedCallback* killable) { killable->notifyAsDeadObject(); });
 }
 
 void DeathMonitor::serviceDied(void* cookie) {
@@ -45,13 +44,13 @@
     deathMonitor->serviceDied();
 }
 
-void DeathMonitor::add(hal::utils::IProtectedCallback* killable) const {
+void DeathMonitor::add(IProtectedCallback* killable) const {
     CHECK(killable != nullptr);
     std::lock_guard guard(mMutex);
     mObjects.push_back(killable);
 }
 
-void DeathMonitor::remove(hal::utils::IProtectedCallback* killable) const {
+void DeathMonitor::remove(IProtectedCallback* killable) const {
     CHECK(killable != nullptr);
     std::lock_guard guard(mMutex);
     const auto removedIter = std::remove(mObjects.begin(), mObjects.end(), killable);
@@ -102,7 +101,7 @@
 }
 
 [[nodiscard]] ::android::base::ScopeGuard<DeathHandler::Cleanup> DeathHandler::protectCallback(
-        hal::utils::IProtectedCallback* killable) const {
+        IProtectedCallback* killable) const {
     CHECK(killable != nullptr);
     kDeathMonitor->add(killable);
     return ::android::base::make_scope_guard(
diff --git a/neuralnetworks/aidl/utils/src/Service.cpp b/neuralnetworks/aidl/utils/src/Service.cpp
index ac182a2..24fbb53 100644
--- a/neuralnetworks/aidl/utils/src/Service.cpp
+++ b/neuralnetworks/aidl/utils/src/Service.cpp
@@ -17,6 +17,7 @@
 #include "Service.h"
 
 #include <AndroidVersionUtil.h>
+#include <aidl/android/hardware/neuralnetworks/IDevice.h>
 #include <android/binder_auto_utils.h>
 #include <android/binder_manager.h>
 #include <android/binder_process.h>
@@ -28,14 +29,38 @@
 #include <string>
 
 #include "Device.h"
+#include "Utils.h"
 
 namespace aidl::android::hardware::neuralnetworks::utils {
+namespace {
 
-nn::GeneralResult<nn::SharedDevice> getDevice(const std::string& instanceName) {
+// Map the AIDL version of an IDevice to NNAPI canonical feature level.
+nn::GeneralResult<nn::Version> getAidlServiceFeatureLevel(IDevice* service) {
+    CHECK(service != nullptr);
+    int aidlVersion;
+    const auto ret = service->getInterfaceVersion(&aidlVersion);
+    HANDLE_ASTATUS(ret) << "getInterfaceVersion failed";
+
+    // For service AIDL versions greater than or equal to the AIDL library version that the runtime
+    // was built against, clamp it to the runtime AIDL library version.
+    aidlVersion = std::min(aidlVersion, IDevice::version);
+
+    // Map stable AIDL versions to canonical versions.
+    auto version = aidlVersionToCanonicalVersion(aidlVersion);
+    if (!version.has_value()) {
+        return NN_ERROR() << "Unknown AIDL service version: " << aidlVersion;
+    }
+    return version.value();
+}
+
+}  // namespace
+
+nn::GeneralResult<nn::SharedDevice> getDevice(
+        const std::string& instanceName, ::android::nn::Version::Level maxFeatureLevelAllowed) {
     auto fullName = std::string(IDevice::descriptor) + "/" + instanceName;
     hal::utils::ResilientDevice::Factory makeDevice =
-            [instanceName,
-             name = std::move(fullName)](bool blocking) -> nn::GeneralResult<nn::SharedDevice> {
+            [instanceName, name = std::move(fullName),
+             maxFeatureLevelAllowed](bool blocking) -> nn::GeneralResult<nn::SharedDevice> {
         std::add_pointer_t<AIBinder*(const char*)> getService;
         if (blocking) {
             if (__builtin_available(android __NNAPI_AIDL_MIN_ANDROID_API__, *)) {
@@ -55,7 +80,9 @@
                    << " returned nullptr";
         }
         ABinderProcess_startThreadPool();
-        return Device::create(instanceName, std::move(service));
+        auto featureLevel = NN_TRY(getAidlServiceFeatureLevel(service.get()));
+        featureLevel.level = std::min(featureLevel.level, maxFeatureLevelAllowed);
+        return Device::create(instanceName, std::move(service), featureLevel);
     };
 
     return hal::utils::ResilientDevice::create(std::move(makeDevice));
diff --git a/neuralnetworks/aidl/utils/src/Utils.cpp b/neuralnetworks/aidl/utils/src/Utils.cpp
index 03407be..f9b4f6e 100644
--- a/neuralnetworks/aidl/utils/src/Utils.cpp
+++ b/neuralnetworks/aidl/utils/src/Utils.cpp
@@ -51,8 +51,9 @@
 }
 
 nn::GeneralResult<common::NativeHandle> clone(const common::NativeHandle& handle) {
+    auto fds = NN_TRY(cloneVec(handle.fds));
     return common::NativeHandle{
-            .fds = NN_TRY(cloneVec(handle.fds)),
+            .fds = std::move(fds),
             .ints = handle.ints,
     };
 }
@@ -63,32 +64,35 @@
     switch (memory.getTag()) {
         case Memory::Tag::ashmem: {
             const auto& ashmem = memory.get<Memory::Tag::ashmem>();
+            auto fd = NN_TRY(clone(ashmem.fd));
             auto handle = common::Ashmem{
-                    .fd = NN_TRY(clone(ashmem.fd)),
+                    .fd = std::move(fd),
                     .size = ashmem.size,
             };
             return Memory::make<Memory::Tag::ashmem>(std::move(handle));
         }
         case Memory::Tag::mappableFile: {
             const auto& memFd = memory.get<Memory::Tag::mappableFile>();
+            auto fd = NN_TRY(clone(memFd.fd));
             auto handle = common::MappableFile{
                     .length = memFd.length,
                     .prot = memFd.prot,
-                    .fd = NN_TRY(clone(memFd.fd)),
+                    .fd = std::move(fd),
                     .offset = memFd.offset,
             };
             return Memory::make<Memory::Tag::mappableFile>(std::move(handle));
         }
         case Memory::Tag::hardwareBuffer: {
             const auto& hardwareBuffer = memory.get<Memory::Tag::hardwareBuffer>();
-            auto handle = graphics::common::HardwareBuffer{
+            auto handle = NN_TRY(clone(hardwareBuffer.handle));
+            auto ahwbHandle = graphics::common::HardwareBuffer{
                     .description = hardwareBuffer.description,
-                    .handle = NN_TRY(clone(hardwareBuffer.handle)),
+                    .handle = std::move(handle),
             };
-            return Memory::make<Memory::Tag::hardwareBuffer>(std::move(handle));
+            return Memory::make<Memory::Tag::hardwareBuffer>(std::move(ahwbHandle));
         }
     }
-    return (NN_ERROR() << "Unrecognized Memory::Tag: " << memory.getTag())
+    return (NN_ERROR() << "Unrecognized Memory::Tag: " << underlyingType(memory.getTag()))
             .
             operator nn::GeneralResult<Memory>();
 }
@@ -103,25 +107,27 @@
     }
     // Using explicit type conversion because std::variant inside the RequestMemoryPool confuses the
     // compiler.
-    return (NN_ERROR() << "Unrecognized request pool tag: " << requestPool.getTag())
+    return (NN_ERROR() << "Unrecognized request pool tag: " << underlyingType(requestPool.getTag()))
             .
             operator nn::GeneralResult<RequestMemoryPool>();
 }
 
 nn::GeneralResult<Request> clone(const Request& request) {
+    auto pools = NN_TRY(clone(request.pools));
     return Request{
             .inputs = request.inputs,
             .outputs = request.outputs,
-            .pools = NN_TRY(clone(request.pools)),
+            .pools = std::move(pools),
     };
 }
 
 nn::GeneralResult<Model> clone(const Model& model) {
+    auto pools = NN_TRY(clone(model.pools));
     return Model{
             .main = model.main,
             .referenced = model.referenced,
             .operandValues = model.operandValues,
-            .pools = NN_TRY(clone(model.pools)),
+            .pools = std::move(pools),
             .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
             .extensionNameToPrefix = model.extensionNameToPrefix,
     };
diff --git a/neuralnetworks/aidl/utils/src/ValidateHal.cpp b/neuralnetworks/aidl/utils/src/ValidateHal.cpp
new file mode 100644
index 0000000..a56de21
--- /dev/null
+++ b/neuralnetworks/aidl/utils/src/ValidateHal.cpp
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "ValidateHal"
+
+#include "ValidateHal.h"
+
+#include "HalUtils.h"
+
+#include <android-base/logging.h>
+#include <nnapi/TypeUtils.h>
+#include <nnapi/hal/aidl/Conversions.h>
+
+#include <algorithm>
+#include <memory>
+#include <set>
+#include <utility>
+#include <vector>
+
+namespace android {
+namespace nn {
+
+bool validateMemoryDesc(
+        const aidl_hal::BufferDesc& desc,
+        const std::vector<std::shared_ptr<aidl_hal::IPreparedModel>>& preparedModels,
+        const std::vector<aidl_hal::BufferRole>& inputRoles,
+        const std::vector<aidl_hal::BufferRole>& outputRoles,
+        std::function<const aidl_hal::Model*(const std::shared_ptr<aidl_hal::IPreparedModel>&)>
+                getModel,
+        std::set<AidlHalPreparedModelRole>* preparedModelRoles,
+        aidl_hal::Operand* combinedOperand) {
+    NN_RET_CHECK(!preparedModels.empty());
+    NN_RET_CHECK(!inputRoles.empty() || !outputRoles.empty());
+
+    std::set<AidlHalPreparedModelRole> roles;
+    std::vector<aidl_hal::Operand> operands;
+    operands.reserve(inputRoles.size() + outputRoles.size());
+    for (const auto& role : inputRoles) {
+        NN_RET_CHECK_GE(role.modelIndex, 0);
+        NN_RET_CHECK_LT(static_cast<size_t>(role.modelIndex), preparedModels.size());
+        const auto& preparedModel = preparedModels[role.modelIndex];
+        NN_RET_CHECK(preparedModel != nullptr);
+        const auto* model = getModel(preparedModel);
+        NN_RET_CHECK(model != nullptr);
+        const auto& inputIndexes = model->main.inputIndexes;
+        NN_RET_CHECK_GE(role.ioIndex, 0);
+        NN_RET_CHECK_LT(static_cast<size_t>(role.ioIndex), inputIndexes.size());
+        NN_RET_CHECK_GT(role.probability, 0.0f);
+        NN_RET_CHECK_LE(role.probability, 1.0f);
+        const auto [it, success] = roles.emplace(preparedModel.get(), IOType::INPUT, role.ioIndex);
+        NN_RET_CHECK(success);
+        operands.push_back(model->main.operands[inputIndexes[role.ioIndex]]);
+    }
+    for (const auto& role : outputRoles) {
+        NN_RET_CHECK_GE(role.modelIndex, 0);
+        NN_RET_CHECK_LT(static_cast<size_t>(role.modelIndex), preparedModels.size());
+        const auto& preparedModel = preparedModels[role.modelIndex];
+        NN_RET_CHECK(preparedModel != nullptr);
+        const auto* model = getModel(preparedModel);
+        NN_RET_CHECK(model != nullptr);
+        const auto& outputIndexes = model->main.outputIndexes;
+        NN_RET_CHECK_GE(role.ioIndex, 0);
+        NN_RET_CHECK_LT(static_cast<size_t>(role.ioIndex), outputIndexes.size());
+        NN_RET_CHECK_GT(role.probability, 0.0f);
+        NN_RET_CHECK_LE(role.probability, 1.0f);
+        const auto [it, success] = roles.emplace(preparedModel.get(), IOType::OUTPUT, role.ioIndex);
+        NN_RET_CHECK(success);
+        operands.push_back(model->main.operands[outputIndexes[role.ioIndex]]);
+    }
+
+    CHECK(!operands.empty());
+    const auto opType = operands[0].type;
+    const auto canonicalOperandType = convert(opType);
+    NN_RET_CHECK(canonicalOperandType.has_value()) << canonicalOperandType.error().message;
+    const bool isExtensionOperand = isExtension(canonicalOperandType.value());
+
+    auto maybeDimensions = toUnsigned(desc.dimensions);
+    NN_RET_CHECK(maybeDimensions.has_value()) << maybeDimensions.error().message;
+    std::vector<uint32_t> dimensions = std::move(maybeDimensions).value();
+
+    for (const auto& operand : operands) {
+        NN_RET_CHECK(operand.type == operands[0].type)
+                << toString(operand.type) << " vs " << toString(operands[0].type);
+        NN_RET_CHECK_EQ(operand.scale, operands[0].scale);
+        NN_RET_CHECK_EQ(operand.zeroPoint, operands[0].zeroPoint);
+        // NOTE: validateMemoryDesc cannot validate extra parameters for extension operand type.
+        if (!isExtensionOperand) {
+            const auto& lhsExtraParams = operand.extraParams;
+            const auto& rhsExtraParams = operands[0].extraParams;
+            NN_RET_CHECK(lhsExtraParams == rhsExtraParams)
+                    << (lhsExtraParams.has_value() ? lhsExtraParams.value().toString()
+                                                   : "std::nullopt")
+                    << " vs "
+                    << (rhsExtraParams.has_value() ? rhsExtraParams.value().toString()
+                                                   : "std::nullopt");
+        }
+        const auto maybeRhsDimensions = toUnsigned(operand.dimensions);
+        NN_RET_CHECK(maybeRhsDimensions.has_value()) << maybeRhsDimensions.error().message;
+        const auto combined = combineDimensions(dimensions, maybeRhsDimensions.value());
+        NN_RET_CHECK(combined.has_value());
+        dimensions = combined.value();
+    }
+
+    // NOTE: validateMemoryDesc cannot validate scalar dimensions with extension operand type.
+    if (!isExtensionOperand) {
+        NN_RET_CHECK(!isNonExtensionScalar(opType) || dimensions.empty())
+                << "invalid dimensions with scalar operand type.";
+    }
+
+    if (preparedModelRoles != nullptr) {
+        *preparedModelRoles = std::move(roles);
+    }
+    if (combinedOperand != nullptr) {
+        *combinedOperand = operands[0];
+        // No need to check that values fit int32_t here, since the original values are obtained
+        // from int32_t.
+        combinedOperand->dimensions = aidl_hal::utils::toSigned(dimensions).value();
+    }
+    return true;
+}
+
+}  // namespace nn
+}  // namespace android
diff --git a/neuralnetworks/aidl/utils/test/DeviceTest.cpp b/neuralnetworks/aidl/utils/test/DeviceTest.cpp
index f121aca..73727b3 100644
--- a/neuralnetworks/aidl/utils/test/DeviceTest.cpp
+++ b/neuralnetworks/aidl/utils/test/DeviceTest.cpp
@@ -17,6 +17,7 @@
 #include "MockBuffer.h"
 #include "MockDevice.h"
 #include "MockPreparedModel.h"
+#include "TestUtils.h"
 
 #include <aidl/android/hardware/neuralnetworks/BnDevice.h>
 #include <android/binder_auto_utils.h>
@@ -60,7 +61,6 @@
                                                 .powerUsage = std::numeric_limits<float>::max()};
 constexpr NumberOfCacheFiles kNumberOfCacheFiles = {.numModelCache = nn::kMaxNumberOfCacheFiles - 1,
                                                     .numDataCache = nn::kMaxNumberOfCacheFiles};
-
 constexpr auto makeStatusOk = [] { return ndk::ScopedAStatus::ok(); };
 
 std::shared_ptr<MockDevice> createMockDevice() {
@@ -123,6 +123,18 @@
     };
 }
 
+const std::vector<nn::TokenValuePair> kHints = {nn::TokenValuePair{.token = 0, .value = {1}}};
+const std::vector<nn::ExtensionNameAndPrefix> kExtensionNameToPrefix = {
+        nn::ExtensionNameAndPrefix{.name = "com.android.nn_test", .prefix = 1}};
+auto makePreparedModelWithConfigReturn(ErrorStatus launchStatus, ErrorStatus returnStatus,
+                                       const std::shared_ptr<MockPreparedModel>& preparedModel) {
+    return [launchStatus, returnStatus, preparedModel](
+                   const Model& /*model*/, const PrepareModelConfig& /*config*/,
+                   const std::shared_ptr<IPreparedModelCallback>& cb) -> ndk::ScopedAStatus {
+        return makePreparedModelReturnImpl(launchStatus, returnStatus, preparedModel, cb);
+    };
+}
+
 auto makePreparedModelFromCacheReturn(ErrorStatus launchStatus, ErrorStatus returnStatus,
                                       const std::shared_ptr<MockPreparedModel>& preparedModel) {
     return [launchStatus, returnStatus, preparedModel](
@@ -146,28 +158,30 @@
     return ndk::ScopedAStatus::fromStatus(STATUS_DEAD_OBJECT);
 };
 
+class DeviceTest : public VersionedAidlUtilsTestBase {};
+
 }  // namespace
 
-TEST(DeviceTest, invalidName) {
+TEST_P(DeviceTest, invalidName) {
     // run test
     const auto device = MockDevice::create();
-    const auto result = Device::create(kInvalidName, device);
+    const auto result = Device::create(kInvalidName, device, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::INVALID_ARGUMENT);
 }
 
-TEST(DeviceTest, invalidDevice) {
+TEST_P(DeviceTest, invalidDevice) {
     // run test
-    const auto result = Device::create(kName, kInvalidDevice);
+    const auto result = Device::create(kName, kInvalidDevice, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::INVALID_ARGUMENT);
 }
 
-TEST(DeviceTest, getVersionStringError) {
+TEST_P(DeviceTest, getVersionStringError) {
     // setup call
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getVersionString(_))
@@ -175,14 +189,14 @@
             .WillOnce(InvokeWithoutArgs(makeGeneralFailure));
 
     // run test
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, getVersionStringTransportFailure) {
+TEST_P(DeviceTest, getVersionStringTransportFailure) {
     // setup call
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getVersionString(_))
@@ -190,14 +204,14 @@
             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
 
     // run test
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, getVersionStringDeadObject) {
+TEST_P(DeviceTest, getVersionStringDeadObject) {
     // setup call
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getVersionString(_))
@@ -205,27 +219,27 @@
             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
 
     // run test
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
 }
 
-TEST(DeviceTest, getTypeError) {
+TEST_P(DeviceTest, getTypeError) {
     // setup call
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getType(_)).Times(1).WillOnce(InvokeWithoutArgs(makeGeneralFailure));
 
     // run test
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, getTypeTransportFailure) {
+TEST_P(DeviceTest, getTypeTransportFailure) {
     // setup call
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getType(_))
@@ -233,14 +247,14 @@
             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
 
     // run test
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, getTypeDeadObject) {
+TEST_P(DeviceTest, getTypeDeadObject) {
     // setup call
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getType(_))
@@ -248,14 +262,14 @@
             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
 
     // run test
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
 }
 
-TEST(DeviceTest, getSupportedExtensionsError) {
+TEST_P(DeviceTest, getSupportedExtensionsError) {
     // setup call
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getSupportedExtensions(_))
@@ -263,14 +277,14 @@
             .WillOnce(InvokeWithoutArgs(makeGeneralFailure));
 
     // run test
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, getSupportedExtensionsTransportFailure) {
+TEST_P(DeviceTest, getSupportedExtensionsTransportFailure) {
     // setup call
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getSupportedExtensions(_))
@@ -278,14 +292,14 @@
             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
 
     // run test
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, getSupportedExtensionsDeadObject) {
+TEST_P(DeviceTest, getSupportedExtensionsDeadObject) {
     // setup call
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getSupportedExtensions(_))
@@ -293,20 +307,20 @@
             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
 
     // run test
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
 }
 
-TEST(DeviceTest, getNumberOfCacheFilesNeeded) {
+TEST_P(DeviceTest, getNumberOfCacheFilesNeeded) {
     // setup call
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getNumberOfCacheFilesNeeded(_)).Times(1);
 
     // run test
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
 
     // verify result
     ASSERT_TRUE(result.has_value());
@@ -315,7 +329,7 @@
     EXPECT_EQ(result.value()->getNumberOfCacheFilesNeeded(), kNumberOfCacheFilesPair);
 }
 
-TEST(DeviceTest, getNumberOfCacheFilesNeededError) {
+TEST_P(DeviceTest, getNumberOfCacheFilesNeededError) {
     // setup call
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getNumberOfCacheFilesNeeded(_))
@@ -323,14 +337,14 @@
             .WillOnce(InvokeWithoutArgs(makeGeneralFailure));
 
     // run test
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, dataCacheFilesExceedsSpecifiedMax) {
+TEST_P(DeviceTest, dataCacheFilesExceedsSpecifiedMax) {
     // setup test
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getNumberOfCacheFilesNeeded(_))
@@ -341,14 +355,14 @@
                             InvokeWithoutArgs(makeStatusOk)));
 
     // run test
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, modelCacheFilesExceedsSpecifiedMax) {
+TEST_P(DeviceTest, modelCacheFilesExceedsSpecifiedMax) {
     // setup test
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getNumberOfCacheFilesNeeded(_))
@@ -359,14 +373,14 @@
                             InvokeWithoutArgs(makeStatusOk)));
 
     // run test
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, getNumberOfCacheFilesNeededTransportFailure) {
+TEST_P(DeviceTest, getNumberOfCacheFilesNeededTransportFailure) {
     // setup call
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getNumberOfCacheFilesNeeded(_))
@@ -374,14 +388,14 @@
             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
 
     // run test
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, getNumberOfCacheFilesNeededDeadObject) {
+TEST_P(DeviceTest, getNumberOfCacheFilesNeededDeadObject) {
     // setup call
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getNumberOfCacheFilesNeeded(_))
@@ -389,14 +403,14 @@
             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
 
     // run test
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
 }
 
-TEST(DeviceTest, getCapabilitiesError) {
+TEST_P(DeviceTest, getCapabilitiesError) {
     // setup call
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getCapabilities(_))
@@ -404,14 +418,14 @@
             .WillOnce(InvokeWithoutArgs(makeGeneralFailure));
 
     // run test
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, getCapabilitiesTransportFailure) {
+TEST_P(DeviceTest, getCapabilitiesTransportFailure) {
     // setup call
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getCapabilities(_))
@@ -419,14 +433,14 @@
             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
 
     // run test
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, getCapabilitiesDeadObject) {
+TEST_P(DeviceTest, getCapabilitiesDeadObject) {
     // setup call
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getCapabilities(_))
@@ -434,17 +448,17 @@
             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
 
     // run test
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
 }
 
-TEST(DeviceTest, getName) {
+TEST_P(DeviceTest, getName) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
 
     // run test
     const auto& name = device->getName();
@@ -453,19 +467,19 @@
     EXPECT_EQ(name, kName);
 }
 
-TEST(DeviceTest, getFeatureLevel) {
+TEST_P(DeviceTest, getFeatureLevel) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
 
     // run test
     const auto featureLevel = device->getFeatureLevel();
 
     // verify result
-    EXPECT_EQ(featureLevel, nn::Version::ANDROID_S);
+    EXPECT_EQ(featureLevel, kVersion);
 }
 
-TEST(DeviceTest, getCachedData) {
+TEST_P(DeviceTest, getCachedData) {
     // setup call
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getVersionString(_)).Times(1);
@@ -474,7 +488,7 @@
     EXPECT_CALL(*mockDevice, getNumberOfCacheFilesNeeded(_)).Times(1);
     EXPECT_CALL(*mockDevice, getCapabilities(_)).Times(1);
 
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
     ASSERT_TRUE(result.has_value())
             << "Failed with " << result.error().code << ": " << result.error().message;
     const auto& device = result.value();
@@ -487,10 +501,10 @@
     EXPECT_EQ(device->getCapabilities(), device->getCapabilities());
 }
 
-TEST(DeviceTest, getSupportedOperations) {
+TEST_P(DeviceTest, getSupportedOperations) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     EXPECT_CALL(*mockDevice, getSupportedOperations(_, _))
             .Times(1)
             .WillOnce(DoAll(
@@ -508,10 +522,10 @@
     EXPECT_THAT(supportedOperations, Each(testing::IsTrue()));
 }
 
-TEST(DeviceTest, getSupportedOperationsError) {
+TEST_P(DeviceTest, getSupportedOperationsError) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     EXPECT_CALL(*mockDevice, getSupportedOperations(_, _))
             .Times(1)
             .WillOnce(InvokeWithoutArgs(makeGeneralFailure));
@@ -524,10 +538,10 @@
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, getSupportedOperationsTransportFailure) {
+TEST_P(DeviceTest, getSupportedOperationsTransportFailure) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     EXPECT_CALL(*mockDevice, getSupportedOperations(_, _))
             .Times(1)
             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
@@ -540,10 +554,10 @@
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, getSupportedOperationsDeadObject) {
+TEST_P(DeviceTest, getSupportedOperationsDeadObject) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     EXPECT_CALL(*mockDevice, getSupportedOperations(_, _))
             .Times(1)
             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
@@ -556,10 +570,12 @@
     EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
 }
 
-TEST(DeviceTest, prepareModel) {
+TEST_P(DeviceTest, prepareModel) {
+    if (kVersion.level > nn::Version::Level::FEATURE_LEVEL_7) return;
+
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     const auto mockPreparedModel = MockPreparedModel::create();
     EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _, _))
             .Times(1)
@@ -568,7 +584,7 @@
 
     // run test
     const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
-                                             nn::Priority::DEFAULT, {}, {}, {}, {});
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_TRUE(result.has_value())
@@ -576,10 +592,12 @@
     EXPECT_NE(result.value(), nullptr);
 }
 
-TEST(DeviceTest, prepareModelLaunchError) {
+TEST_P(DeviceTest, prepareModelLaunchError) {
+    if (kVersion.level > nn::Version::Level::FEATURE_LEVEL_7) return;
+
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _, _))
             .Times(1)
             .WillOnce(Invoke(makePreparedModelReturn(ErrorStatus::GENERAL_FAILURE,
@@ -587,17 +605,19 @@
 
     // run test
     const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
-                                             nn::Priority::DEFAULT, {}, {}, {}, {});
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, prepareModelReturnError) {
+TEST_P(DeviceTest, prepareModelReturnError) {
+    if (kVersion.level > nn::Version::Level::FEATURE_LEVEL_7) return;
+
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _, _))
             .Times(1)
             .WillOnce(Invoke(makePreparedModelReturn(ErrorStatus::NONE,
@@ -605,17 +625,19 @@
 
     // run test
     const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
-                                             nn::Priority::DEFAULT, {}, {}, {}, {});
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, prepareModelNullptrError) {
+TEST_P(DeviceTest, prepareModelNullptrError) {
+    if (kVersion.level > nn::Version::Level::FEATURE_LEVEL_7) return;
+
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _, _))
             .Times(1)
             .WillOnce(
@@ -623,51 +645,57 @@
 
     // run test
     const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
-                                             nn::Priority::DEFAULT, {}, {}, {}, {});
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, prepareModelTransportFailure) {
+TEST_P(DeviceTest, prepareModelTransportFailure) {
+    if (kVersion.level > nn::Version::Level::FEATURE_LEVEL_7) return;
+
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _, _))
             .Times(1)
             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
 
     // run test
     const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
-                                             nn::Priority::DEFAULT, {}, {}, {}, {});
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, prepareModelDeadObject) {
+TEST_P(DeviceTest, prepareModelDeadObject) {
+    if (kVersion.level > nn::Version::Level::FEATURE_LEVEL_7) return;
+
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _, _))
             .Times(1)
             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
 
     // run test
     const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
-                                             nn::Priority::DEFAULT, {}, {}, {}, {});
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
 }
 
-TEST(DeviceTest, prepareModelAsyncCrash) {
+TEST_P(DeviceTest, prepareModelAsyncCrash) {
+    if (kVersion.level > nn::Version::Level::FEATURE_LEVEL_7) return;
+
     // setup test
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     const auto ret = [&device]() {
         DeathMonitor::serviceDied(device->getDeathMonitor());
         return ndk::ScopedAStatus::ok();
@@ -678,17 +706,167 @@
 
     // run test
     const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
-                                             nn::Priority::DEFAULT, {}, {}, {}, {});
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
 }
 
-TEST(DeviceTest, prepareModelFromCache) {
+TEST_P(DeviceTest, prepareModelWithConfig) {
+    if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
+    const auto mockPreparedModel = MockPreparedModel::create();
+    EXPECT_CALL(*mockDevice, prepareModelWithConfig(_, _, _))
+            .Times(1)
+            .WillOnce(Invoke(makePreparedModelWithConfigReturn(ErrorStatus::NONE, ErrorStatus::NONE,
+                                                               mockPreparedModel)));
+
+    // run test
+    const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, kHints,
+                                             kExtensionNameToPrefix);
+
+    // verify result
+    ASSERT_TRUE(result.has_value())
+            << "Failed with " << result.error().code << ": " << result.error().message;
+    EXPECT_NE(result.value(), nullptr);
+}
+
+TEST_P(DeviceTest, prepareModelWithConfigLaunchError) {
+    if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+    // setup call
+    const auto mockDevice = createMockDevice();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
+    EXPECT_CALL(*mockDevice, prepareModelWithConfig(_, _, _))
+            .Times(1)
+            .WillOnce(Invoke(makePreparedModelWithConfigReturn(
+                    ErrorStatus::GENERAL_FAILURE, ErrorStatus::GENERAL_FAILURE, nullptr)));
+
+    // run test
+    const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, kHints,
+                                             kExtensionNameToPrefix);
+
+    // verify result
+    ASSERT_FALSE(result.has_value());
+    EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST_P(DeviceTest, prepareModelWithConfigReturnError) {
+    if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+    // setup call
+    const auto mockDevice = createMockDevice();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
+    EXPECT_CALL(*mockDevice, prepareModelWithConfig(_, _, _))
+            .Times(1)
+            .WillOnce(Invoke(makePreparedModelWithConfigReturn(
+                    ErrorStatus::NONE, ErrorStatus::GENERAL_FAILURE, nullptr)));
+
+    // run test
+    const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, kHints,
+                                             kExtensionNameToPrefix);
+
+    // verify result
+    ASSERT_FALSE(result.has_value());
+    EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST_P(DeviceTest, prepareModelWithConfigNullptrError) {
+    if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+    // setup call
+    const auto mockDevice = createMockDevice();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
+    EXPECT_CALL(*mockDevice, prepareModelWithConfig(_, _, _))
+            .Times(1)
+            .WillOnce(Invoke(makePreparedModelWithConfigReturn(ErrorStatus::NONE, ErrorStatus::NONE,
+                                                               nullptr)));
+
+    // run test
+    const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, kHints,
+                                             kExtensionNameToPrefix);
+
+    // verify result
+    ASSERT_FALSE(result.has_value());
+    EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST_P(DeviceTest, prepareModelWithConfigTransportFailure) {
+    if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+    // setup call
+    const auto mockDevice = createMockDevice();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
+    EXPECT_CALL(*mockDevice, prepareModelWithConfig(_, _, _))
+            .Times(1)
+            .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+    // run test
+    const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, kHints,
+                                             kExtensionNameToPrefix);
+
+    // verify result
+    ASSERT_FALSE(result.has_value());
+    EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST_P(DeviceTest, prepareModelWithConfigDeadObject) {
+    if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+    // setup call
+    const auto mockDevice = createMockDevice();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
+    EXPECT_CALL(*mockDevice, prepareModelWithConfig(_, _, _))
+            .Times(1)
+            .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
+
+    // run test
+    const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, kHints,
+                                             kExtensionNameToPrefix);
+
+    // verify result
+    ASSERT_FALSE(result.has_value());
+    EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
+}
+
+TEST_P(DeviceTest, prepareModelWithConfigAsyncCrash) {
+    if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+    // setup test
+    const auto mockDevice = createMockDevice();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
+    const auto ret = [&device]() {
+        DeathMonitor::serviceDied(device->getDeathMonitor());
+        return ndk::ScopedAStatus::ok();
+    };
+    EXPECT_CALL(*mockDevice, prepareModelWithConfig(_, _, _))
+            .Times(1)
+            .WillOnce(InvokeWithoutArgs(ret));
+
+    // run test
+    const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
+                                             nn::Priority::DEFAULT, {}, {}, {}, {}, kHints,
+                                             kExtensionNameToPrefix);
+
+    // verify result
+    ASSERT_FALSE(result.has_value());
+    EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
+}
+
+TEST_P(DeviceTest, prepareModelFromCache) {
+    // setup call
+    const auto mockDevice = createMockDevice();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     const auto mockPreparedModel = MockPreparedModel::create();
     EXPECT_CALL(*mockDevice, prepareModelFromCache(_, _, _, _, _))
             .Times(1)
@@ -704,10 +882,10 @@
     EXPECT_NE(result.value(), nullptr);
 }
 
-TEST(DeviceTest, prepareModelFromCacheLaunchError) {
+TEST_P(DeviceTest, prepareModelFromCacheLaunchError) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     EXPECT_CALL(*mockDevice, prepareModelFromCache(_, _, _, _, _))
             .Times(1)
             .WillOnce(Invoke(makePreparedModelFromCacheReturn(
@@ -721,10 +899,10 @@
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, prepareModelFromCacheReturnError) {
+TEST_P(DeviceTest, prepareModelFromCacheReturnError) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     EXPECT_CALL(*mockDevice, prepareModelFromCache(_, _, _, _, _))
             .Times(1)
             .WillOnce(Invoke(makePreparedModelFromCacheReturn(
@@ -738,10 +916,10 @@
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, prepareModelFromCacheNullptrError) {
+TEST_P(DeviceTest, prepareModelFromCacheNullptrError) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     EXPECT_CALL(*mockDevice, prepareModelFromCache(_, _, _, _, _))
             .Times(1)
             .WillOnce(Invoke(makePreparedModelFromCacheReturn(ErrorStatus::NONE, ErrorStatus::NONE,
@@ -755,10 +933,10 @@
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, prepareModelFromCacheTransportFailure) {
+TEST_P(DeviceTest, prepareModelFromCacheTransportFailure) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     EXPECT_CALL(*mockDevice, prepareModelFromCache(_, _, _, _, _))
             .Times(1)
             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
@@ -771,10 +949,10 @@
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, prepareModelFromCacheDeadObject) {
+TEST_P(DeviceTest, prepareModelFromCacheDeadObject) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     EXPECT_CALL(*mockDevice, prepareModelFromCache(_, _, _, _, _))
             .Times(1)
             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
@@ -787,10 +965,10 @@
     EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
 }
 
-TEST(DeviceTest, prepareModelFromCacheAsyncCrash) {
+TEST_P(DeviceTest, prepareModelFromCacheAsyncCrash) {
     // setup test
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     const auto ret = [&device]() {
         DeathMonitor::serviceDied(device->getDeathMonitor());
         return ndk::ScopedAStatus::ok();
@@ -807,10 +985,10 @@
     EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
 }
 
-TEST(DeviceTest, allocate) {
+TEST_P(DeviceTest, allocate) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     const auto mockBuffer = DeviceBuffer{.buffer = MockBuffer::create(), .token = 1};
     EXPECT_CALL(*mockDevice, allocate(_, _, _, _, _))
             .Times(1)
@@ -825,10 +1003,10 @@
     EXPECT_NE(result.value(), nullptr);
 }
 
-TEST(DeviceTest, allocateError) {
+TEST_P(DeviceTest, allocateError) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     EXPECT_CALL(*mockDevice, allocate(_, _, _, _, _))
             .Times(1)
             .WillOnce(InvokeWithoutArgs(makeGeneralFailure));
@@ -841,10 +1019,10 @@
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, allocateTransportFailure) {
+TEST_P(DeviceTest, allocateTransportFailure) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     EXPECT_CALL(*mockDevice, allocate(_, _, _, _, _))
             .Times(1)
             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
@@ -857,10 +1035,10 @@
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, allocateDeadObject) {
+TEST_P(DeviceTest, allocateDeadObject) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     EXPECT_CALL(*mockDevice, allocate(_, _, _, _, _))
             .Times(1)
             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
@@ -873,4 +1051,6 @@
     EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
 }
 
+INSTANTIATE_VERSIONED_AIDL_UTILS_TEST(DeviceTest, kAllAidlVersions);
+
 }  // namespace aidl::android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/aidl/utils/test/ExecutionTest.cpp b/neuralnetworks/aidl/utils/test/ExecutionTest.cpp
new file mode 100644
index 0000000..8519290
--- /dev/null
+++ b/neuralnetworks/aidl/utils/test/ExecutionTest.cpp
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "MockExecution.h"
+#include "MockFencedExecutionCallback.h"
+
+#include <aidl/android/hardware/neuralnetworks/IFencedExecutionCallback.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <nnapi/IExecution.h>
+#include <nnapi/TypeUtils.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/aidl/Execution.h>
+
+#include <functional>
+#include <memory>
+
+namespace aidl::android::hardware::neuralnetworks::utils {
+namespace {
+
+using ::testing::_;
+using ::testing::DoAll;
+using ::testing::Invoke;
+using ::testing::InvokeWithoutArgs;
+using ::testing::SetArgPointee;
+
+const std::shared_ptr<IExecution> kInvalidExecution;
+constexpr auto kNoTiming = Timing{.timeOnDeviceNs = -1, .timeInDriverNs = -1};
+
+constexpr auto makeStatusOk = [] { return ndk::ScopedAStatus::ok(); };
+
+constexpr auto makeGeneralFailure = [] {
+    return ndk::ScopedAStatus::fromServiceSpecificError(
+            static_cast<int32_t>(ErrorStatus::GENERAL_FAILURE));
+};
+constexpr auto makeGeneralTransportFailure = [] {
+    return ndk::ScopedAStatus::fromStatus(STATUS_NO_MEMORY);
+};
+constexpr auto makeDeadObjectFailure = [] {
+    return ndk::ScopedAStatus::fromStatus(STATUS_DEAD_OBJECT);
+};
+
+auto makeFencedExecutionResult(const std::shared_ptr<MockFencedExecutionCallback>& callback) {
+    return [callback](const std::vector<ndk::ScopedFileDescriptor>& /*waitFor*/,
+                      int64_t /*deadline*/, int64_t /*duration*/,
+                      FencedExecutionResult* fencedExecutionResult) {
+        *fencedExecutionResult = FencedExecutionResult{.callback = callback,
+                                                       .syncFence = ndk::ScopedFileDescriptor(-1)};
+        return ndk::ScopedAStatus::ok();
+    };
+}
+
+}  // namespace
+
+TEST(ExecutionTest, invalidExecution) {
+    // run test
+    const auto result = Execution::create(kInvalidExecution, {});
+
+    // verify result
+    ASSERT_FALSE(result.has_value());
+    EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST(ExecutionTest, executeSync) {
+    // setup call
+    const auto mockExecution = MockExecution::create();
+    const auto execution = Execution::create(mockExecution, {}).value();
+    const auto mockExecutionResult = ExecutionResult{
+            .outputSufficientSize = true,
+            .outputShapes = {},
+            .timing = kNoTiming,
+    };
+    EXPECT_CALL(*mockExecution, executeSynchronously(_, _))
+            .Times(1)
+            .WillOnce(
+                    DoAll(SetArgPointee<1>(mockExecutionResult), InvokeWithoutArgs(makeStatusOk)));
+
+    // run test
+    const auto result = execution->compute({});
+
+    // verify result
+    EXPECT_TRUE(result.has_value())
+            << "Failed with " << result.error().code << ": " << result.error().message;
+}
+
+TEST(ExecutionTest, executeSyncError) {
+    // setup test
+    const auto mockExecution = MockExecution::create();
+    const auto execution = Execution::create(mockExecution, {}).value();
+    EXPECT_CALL(*mockExecution, executeSynchronously(_, _))
+            .Times(1)
+            .WillOnce(Invoke(makeGeneralFailure));
+
+    // run test
+    const auto result = execution->compute({});
+
+    // verify result
+    ASSERT_FALSE(result.has_value());
+    EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST(ExecutionTest, executeSyncTransportFailure) {
+    // setup test
+    const auto mockExecution = MockExecution::create();
+    const auto execution = Execution::create(mockExecution, {}).value();
+    EXPECT_CALL(*mockExecution, executeSynchronously(_, _))
+            .Times(1)
+            .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+    // run test
+    const auto result = execution->compute({});
+
+    // verify result
+    ASSERT_FALSE(result.has_value());
+    EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST(ExecutionTest, executeSyncDeadObject) {
+    // setup test
+    const auto mockExecution = MockExecution::create();
+    const auto execution = Execution::create(mockExecution, {}).value();
+    EXPECT_CALL(*mockExecution, executeSynchronously(_, _))
+            .Times(1)
+            .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
+
+    // run test
+    const auto result = execution->compute({});
+
+    // verify result
+    ASSERT_FALSE(result.has_value());
+    EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
+}
+
+TEST(ExecutionTest, executeFenced) {
+    // setup call
+    const auto mockExecution = MockExecution::create();
+    const auto execution = Execution::create(mockExecution, {}).value();
+    const auto mockCallback = MockFencedExecutionCallback::create();
+    EXPECT_CALL(*mockCallback, getExecutionInfo(_, _, _))
+            .Times(1)
+            .WillOnce(DoAll(SetArgPointee<0>(kNoTiming), SetArgPointee<1>(kNoTiming),
+                            SetArgPointee<2>(ErrorStatus::NONE), Invoke(makeStatusOk)));
+    EXPECT_CALL(*mockExecution, executeFenced(_, _, _, _))
+            .Times(1)
+            .WillOnce(Invoke(makeFencedExecutionResult(mockCallback)));
+
+    // run test
+    const auto result = execution->computeFenced({}, {}, {});
+
+    // verify result
+    ASSERT_TRUE(result.has_value())
+            << "Failed with " << result.error().code << ": " << result.error().message;
+    const auto& [syncFence, callback] = result.value();
+    EXPECT_EQ(syncFence.syncWait({}), nn::SyncFence::FenceState::SIGNALED);
+    ASSERT_NE(callback, nullptr);
+
+    // get results from callback
+    const auto callbackResult = callback();
+    ASSERT_TRUE(callbackResult.has_value()) << "Failed with " << callbackResult.error().code << ": "
+                                            << callbackResult.error().message;
+}
+
+TEST(ExecutionTest, executeFencedCallbackError) {
+    // setup call
+    const auto mockExecution = MockExecution::create();
+    const auto execution = Execution::create(mockExecution, {}).value();
+    const auto mockCallback = MockFencedExecutionCallback::create();
+    EXPECT_CALL(*mockCallback, getExecutionInfo(_, _, _))
+            .Times(1)
+            .WillOnce(Invoke(DoAll(SetArgPointee<0>(kNoTiming), SetArgPointee<1>(kNoTiming),
+                                   SetArgPointee<2>(ErrorStatus::GENERAL_FAILURE),
+                                   Invoke(makeStatusOk))));
+    EXPECT_CALL(*mockExecution, executeFenced(_, _, _, _))
+            .Times(1)
+            .WillOnce(Invoke(makeFencedExecutionResult(mockCallback)));
+
+    // run test
+    const auto result = execution->computeFenced({}, {}, {});
+
+    // verify result
+    ASSERT_TRUE(result.has_value())
+            << "Failed with " << result.error().code << ": " << result.error().message;
+    const auto& [syncFence, callback] = result.value();
+    EXPECT_NE(syncFence.syncWait({}), nn::SyncFence::FenceState::ACTIVE);
+    ASSERT_NE(callback, nullptr);
+
+    // verify callback failure
+    const auto callbackResult = callback();
+    ASSERT_FALSE(callbackResult.has_value());
+    EXPECT_EQ(callbackResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST(ExecutionTest, executeFencedError) {
+    // setup test
+    const auto mockExecution = MockExecution::create();
+    const auto execution = Execution::create(mockExecution, {}).value();
+    EXPECT_CALL(*mockExecution, executeFenced(_, _, _, _))
+            .Times(1)
+            .WillOnce(InvokeWithoutArgs(makeGeneralFailure));
+
+    // run test
+    const auto result = execution->computeFenced({}, {}, {});
+
+    // verify result
+    ASSERT_FALSE(result.has_value());
+    EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST(ExecutionTest, executeFencedTransportFailure) {
+    // setup test
+    const auto mockExecution = MockExecution::create();
+    const auto execution = Execution::create(mockExecution, {}).value();
+    EXPECT_CALL(*mockExecution, executeFenced(_, _, _, _))
+            .Times(1)
+            .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+    // run test
+    const auto result = execution->computeFenced({}, {}, {});
+
+    // verify result
+    ASSERT_FALSE(result.has_value());
+    EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST(ExecutionTest, executeFencedDeadObject) {
+    // setup test
+    const auto mockExecution = MockExecution::create();
+    const auto execution = Execution::create(mockExecution, {}).value();
+    EXPECT_CALL(*mockExecution, executeFenced(_, _, _, _))
+            .Times(1)
+            .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
+
+    // run test
+    const auto result = execution->computeFenced({}, {}, {});
+
+    // verify result
+    ASSERT_FALSE(result.has_value());
+    EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
+}
+
+}  // namespace aidl::android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/aidl/utils/test/MockBuffer.h b/neuralnetworks/aidl/utils/test/MockBuffer.h
index f77fa86..7a05a0f 100644
--- a/neuralnetworks/aidl/utils/test/MockBuffer.h
+++ b/neuralnetworks/aidl/utils/test/MockBuffer.h
@@ -21,7 +21,6 @@
 #include <android/binder_interface_utils.h>
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
-#include <hidl/Status.h>
 
 namespace aidl::android::hardware::neuralnetworks::utils {
 
diff --git a/neuralnetworks/aidl/utils/test/MockBurst.h b/neuralnetworks/aidl/utils/test/MockBurst.h
index 5083bbd..609bd30 100644
--- a/neuralnetworks/aidl/utils/test/MockBurst.h
+++ b/neuralnetworks/aidl/utils/test/MockBurst.h
@@ -21,7 +21,6 @@
 #include <android/binder_interface_utils.h>
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
-#include <hidl/Status.h>
 
 namespace aidl::android::hardware::neuralnetworks::utils {
 
@@ -32,6 +31,10 @@
                  bool measureTiming, int64_t deadline, int64_t loopTimeoutDuration,
                  ExecutionResult* executionResult),
                 (override));
+    MOCK_METHOD(ndk::ScopedAStatus, executeSynchronouslyWithConfig,
+                (const Request& request, const std::vector<int64_t>& memoryIdentifierTokens,
+                 const ExecutionConfig& config, int64_t deadline, ExecutionResult* executionResult),
+                (override));
     MOCK_METHOD(ndk::ScopedAStatus, releaseMemoryResource, (int64_t memoryIdentifierToken),
                 (override));
 };
diff --git a/neuralnetworks/aidl/utils/test/MockDevice.h b/neuralnetworks/aidl/utils/test/MockDevice.h
index 3a28d55..47b8346 100644
--- a/neuralnetworks/aidl/utils/test/MockDevice.h
+++ b/neuralnetworks/aidl/utils/test/MockDevice.h
@@ -50,6 +50,10 @@
                  const std::vector<uint8_t>& token,
                  const std::shared_ptr<IPreparedModelCallback>& callback),
                 (override));
+    MOCK_METHOD(ndk::ScopedAStatus, prepareModelWithConfig,
+                (const Model& model, const PrepareModelConfig& config,
+                 const std::shared_ptr<IPreparedModelCallback>& callback),
+                (override));
     MOCK_METHOD(ndk::ScopedAStatus, prepareModelFromCache,
                 (int64_t deadline, const std::vector<ndk::ScopedFileDescriptor>& modelCache,
                  const std::vector<ndk::ScopedFileDescriptor>& dataCache,
diff --git a/neuralnetworks/aidl/utils/test/MockExecution.h b/neuralnetworks/aidl/utils/test/MockExecution.h
new file mode 100644
index 0000000..782e54f
--- /dev/null
+++ b/neuralnetworks/aidl/utils/test/MockExecution.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_TEST_MOCK_EXECUTION_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_TEST_MOCK_EXECUTION_H
+
+#include <aidl/android/hardware/neuralnetworks/BnExecution.h>
+#include <android/binder_interface_utils.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+namespace aidl::android::hardware::neuralnetworks::utils {
+
+class MockExecution final : public BnExecution {
+  public:
+    static std::shared_ptr<MockExecution> create();
+
+    MOCK_METHOD(ndk::ScopedAStatus, executeSynchronously,
+                (int64_t deadline, ExecutionResult* executionResult), (override));
+    MOCK_METHOD(ndk::ScopedAStatus, executeFenced,
+                (const std::vector<ndk::ScopedFileDescriptor>& waitFor, int64_t deadline,
+                 int64_t duration, FencedExecutionResult* fencedExecutionResult),
+                (override));
+};
+
+inline std::shared_ptr<MockExecution> MockExecution::create() {
+    return ndk::SharedRefBase::make<MockExecution>();
+}
+
+}  // namespace aidl::android::hardware::neuralnetworks::utils
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_TEST_MOCK_EXECUTION_H
diff --git a/neuralnetworks/aidl/utils/test/MockFencedExecutionCallback.h b/neuralnetworks/aidl/utils/test/MockFencedExecutionCallback.h
index 06f9ea2..29449bb 100644
--- a/neuralnetworks/aidl/utils/test/MockFencedExecutionCallback.h
+++ b/neuralnetworks/aidl/utils/test/MockFencedExecutionCallback.h
@@ -22,7 +22,6 @@
 #include <android/binder_interface_utils.h>
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
-#include <hidl/Status.h>
 
 namespace aidl::android::hardware::neuralnetworks::utils {
 
diff --git a/neuralnetworks/aidl/utils/test/MockPreparedModel.h b/neuralnetworks/aidl/utils/test/MockPreparedModel.h
index a4ae2b7..a5b3b66 100644
--- a/neuralnetworks/aidl/utils/test/MockPreparedModel.h
+++ b/neuralnetworks/aidl/utils/test/MockPreparedModel.h
@@ -17,12 +17,11 @@
 #ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_TEST_MOCK_PREPARED_MODEL_H
 #define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_TEST_MOCK_PREPARED_MODEL_H
 
+#include <aidl/android/hardware/neuralnetworks/BnExecution.h>
 #include <aidl/android/hardware/neuralnetworks/BnPreparedModel.h>
 #include <android/binder_interface_utils.h>
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
-#include <hidl/HidlSupport.h>
-#include <hidl/Status.h>
 
 namespace aidl::android::hardware::neuralnetworks::utils {
 
@@ -39,8 +38,21 @@
                  bool measureTiming, int64_t deadline, int64_t loopTimeoutDuration,
                  int64_t duration, FencedExecutionResult* fencedExecutionResult),
                 (override));
+    MOCK_METHOD(ndk::ScopedAStatus, executeSynchronouslyWithConfig,
+                (const Request& request, const ExecutionConfig& config, int64_t deadline,
+                 ExecutionResult* executionResult),
+                (override));
+    MOCK_METHOD(ndk::ScopedAStatus, executeFencedWithConfig,
+                (const Request& request, const std::vector<ndk::ScopedFileDescriptor>& waitFor,
+                 const ExecutionConfig& config, int64_t deadline, int64_t duration,
+                 FencedExecutionResult* fencedExecutionResult),
+                (override));
     MOCK_METHOD(ndk::ScopedAStatus, configureExecutionBurst, (std::shared_ptr<IBurst> * burst),
                 (override));
+    MOCK_METHOD(ndk::ScopedAStatus, createReusableExecution,
+                (const Request& request, const ExecutionConfig& config,
+                 std::shared_ptr<IExecution>* execution),
+                (override));
 };
 
 inline std::shared_ptr<MockPreparedModel> MockPreparedModel::create() {
diff --git a/neuralnetworks/aidl/utils/test/PreparedModelTest.cpp b/neuralnetworks/aidl/utils/test/PreparedModelTest.cpp
index 8bb5c90..bf6136d 100644
--- a/neuralnetworks/aidl/utils/test/PreparedModelTest.cpp
+++ b/neuralnetworks/aidl/utils/test/PreparedModelTest.cpp
@@ -15,8 +15,10 @@
  */
 
 #include "MockBurst.h"
+#include "MockExecution.h"
 #include "MockFencedExecutionCallback.h"
 #include "MockPreparedModel.h"
+#include "TestUtils.h"
 
 #include <aidl/android/hardware/neuralnetworks/IFencedExecutionCallback.h>
 #include <gmock/gmock.h>
@@ -66,21 +68,40 @@
     };
 }
 
+class PreparedModelTest : public VersionedAidlUtilsTestBase {};
+
+const std::vector<nn::TokenValuePair> kHints = {nn::TokenValuePair{.token = 0, .value = {1}}};
+const std::vector<nn::ExtensionNameAndPrefix> kExtensionNameToPrefix = {
+        nn::ExtensionNameAndPrefix{.name = "com.android.nn_test", .prefix = 1}};
+auto makeFencedExecutionWithConfigResult(
+        const std::shared_ptr<MockFencedExecutionCallback>& callback) {
+    return [callback](const Request& /*request*/,
+                      const std::vector<ndk::ScopedFileDescriptor>& /*waitFor*/,
+                      const ExecutionConfig& /*config*/, int64_t /*deadline*/, int64_t /*duration*/,
+                      FencedExecutionResult* fencedExecutionResult) {
+        *fencedExecutionResult = FencedExecutionResult{.callback = callback,
+                                                       .syncFence = ndk::ScopedFileDescriptor(-1)};
+        return ndk::ScopedAStatus::ok();
+    };
+}
+
 }  // namespace
 
-TEST(PreparedModelTest, invalidPreparedModel) {
+TEST_P(PreparedModelTest, invalidPreparedModel) {
     // run test
-    const auto result = PreparedModel::create(kInvalidPreparedModel);
+    const auto result = PreparedModel::create(kInvalidPreparedModel, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(PreparedModelTest, executeSync) {
+TEST_P(PreparedModelTest, executeSync) {
+    if (kVersion.level >= nn::Version::Level::FEATURE_LEVEL_8) return;
+
     // setup call
     const auto mockPreparedModel = MockPreparedModel::create();
-    const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+    const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
     const auto mockExecutionResult = ExecutionResult{
             .outputSufficientSize = true,
             .outputShapes = {},
@@ -92,65 +113,73 @@
                     DoAll(SetArgPointee<4>(mockExecutionResult), InvokeWithoutArgs(makeStatusOk)));
 
     // run test
-    const auto result = preparedModel->execute({}, {}, {}, {});
+    const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
 
     // verify result
     EXPECT_TRUE(result.has_value())
             << "Failed with " << result.error().code << ": " << result.error().message;
 }
 
-TEST(PreparedModelTest, executeSyncError) {
+TEST_P(PreparedModelTest, executeSyncError) {
+    if (kVersion.level >= nn::Version::Level::FEATURE_LEVEL_8) return;
+
     // setup test
     const auto mockPreparedModel = MockPreparedModel::create();
-    const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+    const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
     EXPECT_CALL(*mockPreparedModel, executeSynchronously(_, _, _, _, _))
             .Times(1)
             .WillOnce(Invoke(makeGeneralFailure));
 
     // run test
-    const auto result = preparedModel->execute({}, {}, {}, {});
+    const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(PreparedModelTest, executeSyncTransportFailure) {
+TEST_P(PreparedModelTest, executeSyncTransportFailure) {
+    if (kVersion.level >= nn::Version::Level::FEATURE_LEVEL_8) return;
+
     // setup test
     const auto mockPreparedModel = MockPreparedModel::create();
-    const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+    const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
     EXPECT_CALL(*mockPreparedModel, executeSynchronously(_, _, _, _, _))
             .Times(1)
             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
 
     // run test
-    const auto result = preparedModel->execute({}, {}, {}, {});
+    const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(PreparedModelTest, executeSyncDeadObject) {
+TEST_P(PreparedModelTest, executeSyncDeadObject) {
+    if (kVersion.level >= nn::Version::Level::FEATURE_LEVEL_8) return;
+
     // setup test
     const auto mockPreparedModel = MockPreparedModel::create();
-    const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+    const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
     EXPECT_CALL(*mockPreparedModel, executeSynchronously(_, _, _, _, _))
             .Times(1)
             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
 
     // run test
-    const auto result = preparedModel->execute({}, {}, {}, {});
+    const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
 }
 
-TEST(PreparedModelTest, executeFenced) {
+TEST_P(PreparedModelTest, executeFenced) {
+    if (kVersion.level >= nn::Version::Level::FEATURE_LEVEL_8) return;
+
     // setup call
     const auto mockPreparedModel = MockPreparedModel::create();
-    const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+    const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
     const auto mockCallback = MockFencedExecutionCallback::create();
     EXPECT_CALL(*mockCallback, getExecutionInfo(_, _, _))
             .Times(1)
@@ -161,7 +190,7 @@
             .WillOnce(Invoke(makeFencedExecutionResult(mockCallback)));
 
     // run test
-    const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
+    const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_TRUE(result.has_value())
@@ -176,10 +205,12 @@
                                             << callbackResult.error().message;
 }
 
-TEST(PreparedModelTest, executeFencedCallbackError) {
+TEST_P(PreparedModelTest, executeFencedCallbackError) {
+    if (kVersion.level >= nn::Version::Level::FEATURE_LEVEL_8) return;
+
     // setup call
     const auto mockPreparedModel = MockPreparedModel::create();
-    const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+    const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
     const auto mockCallback = MockFencedExecutionCallback::create();
     EXPECT_CALL(*mockCallback, getExecutionInfo(_, _, _))
             .Times(1)
@@ -191,7 +222,7 @@
             .WillOnce(Invoke(makeFencedExecutionResult(mockCallback)));
 
     // run test
-    const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
+    const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_TRUE(result.has_value())
@@ -206,59 +237,67 @@
     EXPECT_EQ(callbackResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(PreparedModelTest, executeFencedError) {
+TEST_P(PreparedModelTest, executeFencedError) {
+    if (kVersion.level >= nn::Version::Level::FEATURE_LEVEL_8) return;
+
     // setup test
     const auto mockPreparedModel = MockPreparedModel::create();
-    const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+    const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
     EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
             .Times(1)
             .WillOnce(InvokeWithoutArgs(makeGeneralFailure));
 
     // run test
-    const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
+    const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(PreparedModelTest, executeFencedTransportFailure) {
+TEST_P(PreparedModelTest, executeFencedTransportFailure) {
+    if (kVersion.level >= nn::Version::Level::FEATURE_LEVEL_8) return;
+
     // setup test
     const auto mockPreparedModel = MockPreparedModel::create();
-    const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+    const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
     EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
             .Times(1)
             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
 
     // run test
-    const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
+    const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(PreparedModelTest, executeFencedDeadObject) {
+TEST_P(PreparedModelTest, executeFencedDeadObject) {
+    if (kVersion.level >= nn::Version::Level::FEATURE_LEVEL_8) return;
+
     // setup test
     const auto mockPreparedModel = MockPreparedModel::create();
-    const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+    const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
     EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
             .Times(1)
             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
 
     // run test
-    const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
+    const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
 }
 
-TEST(PreparedModelTest, reusableExecuteSync) {
+TEST_P(PreparedModelTest, reusableExecuteSync) {
+    if (kVersion.level >= nn::Version::Level::FEATURE_LEVEL_8) return;
+
     // setup call
     const uint32_t kNumberOfComputations = 2;
     const auto mockPreparedModel = MockPreparedModel::create();
-    const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+    const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
     const auto mockExecutionResult = ExecutionResult{
             .outputSufficientSize = true,
             .outputShapes = {},
@@ -270,7 +309,7 @@
                     DoAll(SetArgPointee<4>(mockExecutionResult), InvokeWithoutArgs(makeStatusOk)));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -283,16 +322,18 @@
     }
 }
 
-TEST(PreparedModelTest, reusableExecuteSyncError) {
+TEST_P(PreparedModelTest, reusableExecuteSyncError) {
+    if (kVersion.level >= nn::Version::Level::FEATURE_LEVEL_8) return;
+
     // setup test
     const auto mockPreparedModel = MockPreparedModel::create();
-    const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+    const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
     EXPECT_CALL(*mockPreparedModel, executeSynchronously(_, _, _, _, _))
             .Times(1)
             .WillOnce(Invoke(makeGeneralFailure));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -303,16 +344,18 @@
     EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(PreparedModelTest, reusableExecuteSyncTransportFailure) {
+TEST_P(PreparedModelTest, reusableExecuteSyncTransportFailure) {
+    if (kVersion.level >= nn::Version::Level::FEATURE_LEVEL_8) return;
+
     // setup test
     const auto mockPreparedModel = MockPreparedModel::create();
-    const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+    const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
     EXPECT_CALL(*mockPreparedModel, executeSynchronously(_, _, _, _, _))
             .Times(1)
             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -323,16 +366,18 @@
     EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(PreparedModelTest, reusableExecuteSyncDeadObject) {
+TEST_P(PreparedModelTest, reusableExecuteSyncDeadObject) {
+    if (kVersion.level >= nn::Version::Level::FEATURE_LEVEL_8) return;
+
     // setup test
     const auto mockPreparedModel = MockPreparedModel::create();
-    const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+    const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
     EXPECT_CALL(*mockPreparedModel, executeSynchronously(_, _, _, _, _))
             .Times(1)
             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -343,11 +388,13 @@
     EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::DEAD_OBJECT);
 }
 
-TEST(PreparedModelTest, reusableExecuteFenced) {
+TEST_P(PreparedModelTest, reusableExecuteFenced) {
+    if (kVersion.level >= nn::Version::Level::FEATURE_LEVEL_8) return;
+
     // setup call
     const uint32_t kNumberOfComputations = 2;
     const auto mockPreparedModel = MockPreparedModel::create();
-    const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+    const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
     const auto mockCallback = MockFencedExecutionCallback::create();
     EXPECT_CALL(*mockCallback, getExecutionInfo(_, _, _))
             .Times(kNumberOfComputations)
@@ -358,7 +405,7 @@
             .WillRepeatedly(Invoke(makeFencedExecutionResult(mockCallback)));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -379,10 +426,12 @@
     }
 }
 
-TEST(PreparedModelTest, reusableExecuteFencedCallbackError) {
+TEST_P(PreparedModelTest, reusableExecuteFencedCallbackError) {
+    if (kVersion.level >= nn::Version::Level::FEATURE_LEVEL_8) return;
+
     // setup call
     const auto mockPreparedModel = MockPreparedModel::create();
-    const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+    const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
     const auto mockCallback = MockFencedExecutionCallback::create();
     EXPECT_CALL(*mockCallback, getExecutionInfo(_, _, _))
             .Times(1)
@@ -394,7 +443,7 @@
             .WillOnce(Invoke(makeFencedExecutionResult(mockCallback)));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -413,16 +462,18 @@
     EXPECT_EQ(callbackResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(PreparedModelTest, reusableExecuteFencedError) {
+TEST_P(PreparedModelTest, reusableExecuteFencedError) {
+    if (kVersion.level >= nn::Version::Level::FEATURE_LEVEL_8) return;
+
     // setup test
     const auto mockPreparedModel = MockPreparedModel::create();
-    const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+    const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
     EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
             .Times(1)
             .WillOnce(InvokeWithoutArgs(makeGeneralFailure));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -433,16 +484,18 @@
     EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(PreparedModelTest, reusableExecuteFencedTransportFailure) {
+TEST_P(PreparedModelTest, reusableExecuteFencedTransportFailure) {
+    if (kVersion.level >= nn::Version::Level::FEATURE_LEVEL_8) return;
+
     // setup test
     const auto mockPreparedModel = MockPreparedModel::create();
-    const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+    const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
     EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
             .Times(1)
             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -453,16 +506,18 @@
     EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(PreparedModelTest, reusableExecuteFencedDeadObject) {
+TEST_P(PreparedModelTest, reusableExecuteFencedDeadObject) {
+    if (kVersion.level >= nn::Version::Level::FEATURE_LEVEL_8) return;
+
     // setup test
     const auto mockPreparedModel = MockPreparedModel::create();
-    const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+    const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
     EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
             .Times(1)
             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
 
     // create execution
-    const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+    const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
     ASSERT_TRUE(createResult.has_value())
             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
     ASSERT_NE(createResult.value(), nullptr);
@@ -473,14 +528,214 @@
     EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::DEAD_OBJECT);
 }
 
-TEST(PreparedModelTest, configureExecutionBurst) {
+TEST_P(PreparedModelTest, executeSyncWithConfig) {
+    if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+    // setup call
+    const auto mockPreparedModel = MockPreparedModel::create();
+    const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
+    const auto mockExecutionResult = ExecutionResult{
+            .outputSufficientSize = true,
+            .outputShapes = {},
+            .timing = kNoTiming,
+    };
+    EXPECT_CALL(*mockPreparedModel, executeSynchronouslyWithConfig(_, _, _, _))
+            .Times(1)
+            .WillOnce(
+                    DoAll(SetArgPointee<3>(mockExecutionResult), InvokeWithoutArgs(makeStatusOk)));
+
+    // run test
+    const auto result = preparedModel->execute({}, {}, {}, {}, kHints, kExtensionNameToPrefix);
+
+    // verify result
+    EXPECT_TRUE(result.has_value())
+            << "Failed with " << result.error().code << ": " << result.error().message;
+}
+
+TEST_P(PreparedModelTest, executeSyncWithConfigError) {
+    if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+    // setup test
+    const auto mockPreparedModel = MockPreparedModel::create();
+    const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
+    EXPECT_CALL(*mockPreparedModel, executeSynchronouslyWithConfig(_, _, _, _))
+            .Times(1)
+            .WillOnce(Invoke(makeGeneralFailure));
+
+    // run test
+    const auto result = preparedModel->execute({}, {}, {}, {}, kHints, kExtensionNameToPrefix);
+
+    // verify result
+    ASSERT_FALSE(result.has_value());
+    EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST_P(PreparedModelTest, executeSyncWithConfigTransportFailure) {
+    if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+    // setup test
+    const auto mockPreparedModel = MockPreparedModel::create();
+    const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
+    EXPECT_CALL(*mockPreparedModel, executeSynchronouslyWithConfig(_, _, _, _))
+            .Times(1)
+            .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+    // run test
+    const auto result = preparedModel->execute({}, {}, {}, {}, kHints, kExtensionNameToPrefix);
+
+    // verify result
+    ASSERT_FALSE(result.has_value());
+    EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST_P(PreparedModelTest, executeSyncWithConfigDeadObject) {
+    if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+    // setup test
+    const auto mockPreparedModel = MockPreparedModel::create();
+    const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
+    EXPECT_CALL(*mockPreparedModel, executeSynchronouslyWithConfig(_, _, _, _))
+            .Times(1)
+            .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
+
+    // run test
+    const auto result = preparedModel->execute({}, {}, {}, {}, kHints, kExtensionNameToPrefix);
+
+    // verify result
+    ASSERT_FALSE(result.has_value());
+    EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
+}
+
+TEST_P(PreparedModelTest, executeFencedWithConfig) {
+    if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+    // setup call
+    const auto mockPreparedModel = MockPreparedModel::create();
+    const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
+    const auto mockCallback = MockFencedExecutionCallback::create();
+    EXPECT_CALL(*mockCallback, getExecutionInfo(_, _, _))
+            .Times(1)
+            .WillOnce(DoAll(SetArgPointee<0>(kNoTiming), SetArgPointee<1>(kNoTiming),
+                            SetArgPointee<2>(ErrorStatus::NONE), Invoke(makeStatusOk)));
+    EXPECT_CALL(*mockPreparedModel, executeFencedWithConfig(_, _, _, _, _, _))
+            .Times(1)
+            .WillOnce(Invoke(makeFencedExecutionWithConfigResult(mockCallback)));
+
+    // run test
+    const auto result =
+            preparedModel->executeFenced({}, {}, {}, {}, {}, {}, kHints, kExtensionNameToPrefix);
+
+    // verify result
+    ASSERT_TRUE(result.has_value())
+            << "Failed with " << result.error().code << ": " << result.error().message;
+    const auto& [syncFence, callback] = result.value();
+    EXPECT_EQ(syncFence.syncWait({}), nn::SyncFence::FenceState::SIGNALED);
+    ASSERT_NE(callback, nullptr);
+
+    // get results from callback
+    const auto callbackResult = callback();
+    ASSERT_TRUE(callbackResult.has_value()) << "Failed with " << callbackResult.error().code << ": "
+                                            << callbackResult.error().message;
+}
+
+TEST_P(PreparedModelTest, executeFencedWithConfigCallbackError) {
+    if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+    // setup call
+    const auto mockPreparedModel = MockPreparedModel::create();
+    const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
+    const auto mockCallback = MockFencedExecutionCallback::create();
+    EXPECT_CALL(*mockCallback, getExecutionInfo(_, _, _))
+            .Times(1)
+            .WillOnce(Invoke(DoAll(SetArgPointee<0>(kNoTiming), SetArgPointee<1>(kNoTiming),
+                                   SetArgPointee<2>(ErrorStatus::GENERAL_FAILURE),
+                                   Invoke(makeStatusOk))));
+    EXPECT_CALL(*mockPreparedModel, executeFencedWithConfig(_, _, _, _, _, _))
+            .Times(1)
+            .WillOnce(Invoke(makeFencedExecutionWithConfigResult(mockCallback)));
+
+    // run test
+    const auto result =
+            preparedModel->executeFenced({}, {}, {}, {}, {}, {}, kHints, kExtensionNameToPrefix);
+
+    // verify result
+    ASSERT_TRUE(result.has_value())
+            << "Failed with " << result.error().code << ": " << result.error().message;
+    const auto& [syncFence, callback] = result.value();
+    EXPECT_NE(syncFence.syncWait({}), nn::SyncFence::FenceState::ACTIVE);
+    ASSERT_NE(callback, nullptr);
+
+    // verify callback failure
+    const auto callbackResult = callback();
+    ASSERT_FALSE(callbackResult.has_value());
+    EXPECT_EQ(callbackResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST_P(PreparedModelTest, executeFencedWithConfigError) {
+    if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+    // setup test
+    const auto mockPreparedModel = MockPreparedModel::create();
+    const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
+    EXPECT_CALL(*mockPreparedModel, executeFencedWithConfig(_, _, _, _, _, _))
+            .Times(1)
+            .WillOnce(InvokeWithoutArgs(makeGeneralFailure));
+
+    // run test
+    const auto result =
+            preparedModel->executeFenced({}, {}, {}, {}, {}, {}, kHints, kExtensionNameToPrefix);
+
+    // verify result
+    ASSERT_FALSE(result.has_value());
+    EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST_P(PreparedModelTest, executeFencedWithConfigTransportFailure) {
+    if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+    // setup test
+    const auto mockPreparedModel = MockPreparedModel::create();
+    const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
+    EXPECT_CALL(*mockPreparedModel, executeFencedWithConfig(_, _, _, _, _, _))
+            .Times(1)
+            .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+    // run test
+    const auto result =
+            preparedModel->executeFenced({}, {}, {}, {}, {}, {}, kHints, kExtensionNameToPrefix);
+
+    // verify result
+    ASSERT_FALSE(result.has_value());
+    EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST_P(PreparedModelTest, executeFencedWithConfigDeadObject) {
+    if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+    // setup test
+    const auto mockPreparedModel = MockPreparedModel::create();
+    const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
+    EXPECT_CALL(*mockPreparedModel, executeFencedWithConfig(_, _, _, _, _, _))
+            .Times(1)
+            .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
+
+    // run test
+    const auto result =
+            preparedModel->executeFenced({}, {}, {}, {}, {}, {}, kHints, kExtensionNameToPrefix);
+
+    // verify result
+    ASSERT_FALSE(result.has_value());
+    EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
+}
+
+TEST_P(PreparedModelTest, configureExecutionBurst) {
     // setup test
     const auto mockPreparedModel = MockPreparedModel::create();
     const auto mockBurst = ndk::SharedRefBase::make<MockBurst>();
     EXPECT_CALL(*mockPreparedModel, configureExecutionBurst(_))
             .Times(1)
             .WillOnce(DoAll(SetArgPointee<0>(mockBurst), Invoke(makeStatusOk)));
-    const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+    const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
 
     // run test
     const auto result = preparedModel->configureExecutionBurst();
@@ -491,13 +746,13 @@
     EXPECT_NE(result.value(), nullptr);
 }
 
-TEST(PreparedModelTest, configureExecutionBurstError) {
+TEST_P(PreparedModelTest, configureExecutionBurstError) {
     // setup test
     const auto mockPreparedModel = MockPreparedModel::create();
     EXPECT_CALL(*mockPreparedModel, configureExecutionBurst(_))
             .Times(1)
             .WillOnce(InvokeWithoutArgs(makeGeneralFailure));
-    const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+    const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
 
     // run test
     const auto result = preparedModel->configureExecutionBurst();
@@ -507,13 +762,13 @@
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(PreparedModelTest, configureExecutionBurstTransportFailure) {
+TEST_P(PreparedModelTest, configureExecutionBurstTransportFailure) {
     // setup test
     const auto mockPreparedModel = MockPreparedModel::create();
     EXPECT_CALL(*mockPreparedModel, configureExecutionBurst(_))
             .Times(1)
             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
-    const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+    const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
 
     // run test
     const auto result = preparedModel->configureExecutionBurst();
@@ -523,13 +778,13 @@
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(PreparedModelTest, configureExecutionBurstDeadObject) {
+TEST_P(PreparedModelTest, configureExecutionBurstDeadObject) {
     // setup test
     const auto mockPreparedModel = MockPreparedModel::create();
     EXPECT_CALL(*mockPreparedModel, configureExecutionBurst(_))
             .Times(1)
             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
-    const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+    const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
 
     // run test
     const auto result = preparedModel->configureExecutionBurst();
@@ -539,10 +794,84 @@
     EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
 }
 
-TEST(PreparedModelTest, getUnderlyingResource) {
+TEST_P(PreparedModelTest, createReusableExecution) {
+    if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
     // setup test
     const auto mockPreparedModel = MockPreparedModel::create();
-    const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
+    const auto mockExecution = ndk::SharedRefBase::make<MockExecution>();
+    EXPECT_CALL(*mockPreparedModel, createReusableExecution(_, _, _))
+            .Times(1)
+            .WillOnce(DoAll(SetArgPointee<2>(mockExecution), Invoke(makeStatusOk)));
+    const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
+
+    // run test
+    const auto result = preparedModel->createReusableExecution({}, {}, {}, {}, {});
+
+    // verify result
+    ASSERT_TRUE(result.has_value())
+            << "Failed with " << result.error().code << ": " << result.error().message;
+    EXPECT_NE(result.value(), nullptr);
+}
+
+TEST_P(PreparedModelTest, createReusableExecutionError) {
+    if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+    // setup test
+    const auto mockPreparedModel = MockPreparedModel::create();
+    EXPECT_CALL(*mockPreparedModel, createReusableExecution(_, _, _))
+            .Times(1)
+            .WillOnce(InvokeWithoutArgs(makeGeneralFailure));
+    const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
+
+    // run test
+    const auto result = preparedModel->createReusableExecution({}, {}, {}, {}, {});
+
+    // verify result
+    ASSERT_FALSE(result.has_value());
+    EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST_P(PreparedModelTest, createReusableExecutionTransportFailure) {
+    if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+    // setup test
+    const auto mockPreparedModel = MockPreparedModel::create();
+    EXPECT_CALL(*mockPreparedModel, createReusableExecution(_, _, _))
+            .Times(1)
+            .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+    const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
+
+    // run test
+    const auto result = preparedModel->createReusableExecution({}, {}, {}, {}, {});
+
+    // verify result
+    ASSERT_FALSE(result.has_value());
+    EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST_P(PreparedModelTest, createReusableExecutionDeadObject) {
+    if (kVersion.level < nn::Version::Level::FEATURE_LEVEL_8) return;
+
+    // setup test
+    const auto mockPreparedModel = MockPreparedModel::create();
+    EXPECT_CALL(*mockPreparedModel, createReusableExecution(_, _, _))
+            .Times(1)
+            .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
+    const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
+
+    // run test
+    const auto result = preparedModel->createReusableExecution({}, {}, {}, {}, {});
+
+    // verify result
+    ASSERT_FALSE(result.has_value());
+    EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
+}
+
+TEST_P(PreparedModelTest, getUnderlyingResource) {
+    // setup test
+    const auto mockPreparedModel = MockPreparedModel::create();
+    const auto preparedModel = PreparedModel::create(mockPreparedModel, kVersion).value();
 
     // run test
     const auto resource = preparedModel->getUnderlyingResource();
@@ -554,4 +883,6 @@
     EXPECT_EQ(maybeMock->get(), mockPreparedModel.get());
 }
 
+INSTANTIATE_VERSIONED_AIDL_UTILS_TEST(PreparedModelTest, kAllAidlVersions);
+
 }  // namespace aidl::android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/aidl/utils/test/TestUtils.cpp b/neuralnetworks/aidl/utils/test/TestUtils.cpp
new file mode 100644
index 0000000..9abec88
--- /dev/null
+++ b/neuralnetworks/aidl/utils/test/TestUtils.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "TestUtils.h"
+
+#include <android-base/logging.h>
+#include <gtest/gtest.h>
+#include <nnapi/TypeUtils.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/CommonUtils.h>
+#include <string>
+
+namespace aidl::android::hardware::neuralnetworks::utils {
+
+std::string printTestVersion(const testing::TestParamInfo<nn::Version>& info) {
+    switch (info.param.level) {
+        case nn::Version::Level::FEATURE_LEVEL_5:
+            return "v1";
+        case nn::Version::Level::FEATURE_LEVEL_6:
+            return "v2";
+        case nn::Version::Level::FEATURE_LEVEL_7:
+            return "v3";
+        case nn::Version::Level::FEATURE_LEVEL_8:
+            return "v4";
+        default:
+            LOG(FATAL) << "Invalid AIDL version: " << info.param;
+            return "invalid";
+    }
+}
+
+}  // namespace aidl::android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/aidl/utils/test/TestUtils.h b/neuralnetworks/aidl/utils/test/TestUtils.h
new file mode 100644
index 0000000..23f734a
--- /dev/null
+++ b/neuralnetworks/aidl/utils/test/TestUtils.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_TEST_TEST_UTILS_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_TEST_TEST_UTILS_H
+
+#include <gtest/gtest.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/CommonUtils.h>
+#include <string>
+
+namespace aidl::android::hardware::neuralnetworks::utils {
+
+class VersionedAidlUtilsTestBase : public ::testing::TestWithParam<nn::Version> {
+  protected:
+    const nn::Version kVersion = GetParam();
+};
+
+std::string printTestVersion(const testing::TestParamInfo<nn::Version>& info);
+
+inline const auto kAllAidlVersions =
+        ::testing::Values(nn::kVersionFeatureLevel5, nn::kVersionFeatureLevel6,
+                          nn::kVersionFeatureLevel7, nn::kVersionFeatureLevel8);
+
+#define INSTANTIATE_VERSIONED_AIDL_UTILS_TEST(TestSuite, versions) \
+    INSTANTIATE_TEST_SUITE_P(Versioned, TestSuite, versions, printTestVersion)
+
+}  // namespace aidl::android::hardware::neuralnetworks::utils
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_AIDL_UTILS_TEST_TEST_UTILS_H
diff --git a/neuralnetworks/aidl/vts/OWNERS b/neuralnetworks/aidl/vts/OWNERS
deleted file mode 100644
index 6719a5b..0000000
--- a/neuralnetworks/aidl/vts/OWNERS
+++ /dev/null
@@ -1,12 +0,0 @@
-# Neuralnetworks team
-butlermichael@google.com
-dgross@google.com
-jeanluc@google.com
-levp@google.com
-miaowang@google.com
-mikie@google.com
-mks@google.com
-pszczepaniak@google.com
-slavash@google.com
-vddang@google.com
-xusongw@google.com
diff --git a/neuralnetworks/aidl/vts/functional/Android.bp b/neuralnetworks/aidl/vts/functional/Android.bp
index 998cd83..04b4a45 100644
--- a/neuralnetworks/aidl/vts/functional/Android.bp
+++ b/neuralnetworks/aidl/vts/functional/Android.bp
@@ -26,9 +26,15 @@
 cc_test {
     name: "VtsHalNeuralnetworksTargetTest",
     defaults: [
+        "neuralnetworks_use_latest_utils_hal_aidl",
         "neuralnetworks_vts_functional_defaults",
         "use_libaidlvintf_gtest_helper_static",
     ],
+    host_supported: true,
+    tidy_timeout_srcs: [
+        "CompilationCachingTests.cpp",
+        "MemoryDomainTests.cpp",
+    ],
     srcs: [
         "BasicTests.cpp",
         "Callbacks.cpp",
@@ -45,24 +51,14 @@
     ],
     shared_libs: [
         "libbinder_ndk",
-        "libnativewindow",
-        "libvndksupport",
     ],
     static_libs: [
-        "android.hardware.common-V2-ndk_platform",
-        "android.hardware.graphics.common-V2-ndk_platform",
-        "android.hardware.neuralnetworks-V2-ndk_platform",
-        "android.hidl.allocator@1.0",
-        "android.hidl.memory@1.0",
         "libaidlcommonsupport",
-        "libgmock",
-        "libhidlmemory",
+        "libneuralnetworks_common",
         "libneuralnetworks_generated_test_harness",
-        "libneuralnetworks_utils",
-        "libsync",
-        "neuralnetworks_utils_hal_aidl",
     ],
     whole_static_libs: [
+        "neuralnetworks_generated_AIDL_V3_example",
         "neuralnetworks_generated_AIDL_V2_example",
         "neuralnetworks_generated_V1_0_example",
         "neuralnetworks_generated_V1_1_example",
@@ -75,6 +71,34 @@
     ],
     test_suites: [
         "general-tests",
-        "vts",
     ],
+    target: {
+        android: {
+            shared_libs: [
+                "libnativewindow",
+                "libvndksupport",
+            ],
+            static_libs: [
+                "libsync",
+            ],
+            test_suites: [
+                "vts",
+            ],
+            test_config: "AndroidTestDevice.xml",
+        },
+        host: {
+            shared_libs: [
+                "libtextclassifier_hash",
+            ],
+            static_libs: [
+                "neuralnetworks_canonical_sample_driver",
+                "neuralnetworks_utils_hal_adapter_aidl",
+            ],
+            exclude_static_libs: [
+                "VtsHalHidlTestUtils",
+                "libaidlvintf_gtest_helper",
+            ],
+            test_config: "AndroidTestHost.xml",
+        },
+    },
 }
diff --git a/neuralnetworks/aidl/vts/functional/AndroidTest.xml b/neuralnetworks/aidl/vts/functional/AndroidTestDevice.xml
similarity index 100%
rename from neuralnetworks/aidl/vts/functional/AndroidTest.xml
rename to neuralnetworks/aidl/vts/functional/AndroidTestDevice.xml
diff --git a/neuralnetworks/aidl/vts/functional/AndroidTestHost.xml b/neuralnetworks/aidl/vts/functional/AndroidTestHost.xml
new file mode 100644
index 0000000..7372a31
--- /dev/null
+++ b/neuralnetworks/aidl/vts/functional/AndroidTestHost.xml
@@ -0,0 +1,22 @@
+<?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 VtsHalNeuralnetworksTargetTest.">
+    <test class="com.android.tradefed.testtype.HostGTest" >
+        <option name="module-name" value="VtsHalNeuralnetworksTargetTest" />
+        <option name="native-test-timeout" value="15m" />
+    </test>
+</configuration>
+
diff --git a/neuralnetworks/aidl/vts/functional/CompilationCachingTests.cpp b/neuralnetworks/aidl/vts/functional/CompilationCachingTests.cpp
index 77208aa..da0fe64 100644
--- a/neuralnetworks/aidl/vts/functional/CompilationCachingTests.cpp
+++ b/neuralnetworks/aidl/vts/functional/CompilationCachingTests.cpp
@@ -23,7 +23,6 @@
 #include <fcntl.h>
 #include <ftw.h>
 #include <gtest/gtest.h>
-#include <hidlmemory/mapping.h>
 #include <unistd.h>
 
 #include <cstdio>
@@ -34,7 +33,6 @@
 
 #include "Callbacks.h"
 #include "GeneratedTestHarness.h"
-#include "MemoryUtils.h"
 #include "TestHarness.h"
 #include "Utils.h"
 #include "VtsHalNeuralnetworks.h"
@@ -229,7 +227,11 @@
 
         // Create cache directory. The cache directory and a temporary cache file is always created
         // to test the behavior of prepareModelFromCache, even when caching is not supported.
+#ifdef __ANDROID__
         char cacheDirTemp[] = "/data/local/tmp/TestCompilationCachingXXXXXX";
+#else   // __ANDROID__
+        char cacheDirTemp[] = "/tmp/TestCompilationCachingXXXXXX";
+#endif  // __ANDROID__
         char* cacheDir = mkdtemp(cacheDirTemp);
         ASSERT_NE(cacheDir, nullptr);
         mCacheDir = cacheDir;
@@ -1066,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/GeneratedTestHarness.cpp b/neuralnetworks/aidl/vts/functional/GeneratedTestHarness.cpp
index f67fd34..dcf8451 100644
--- a/neuralnetworks/aidl/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/aidl/vts/functional/GeneratedTestHarness.cpp
@@ -20,7 +20,6 @@
 #include <aidl/android/hardware/neuralnetworks/RequestMemoryPool.h>
 #include <android-base/logging.h>
 #include <android/binder_auto_utils.h>
-#include <android/sync.h>
 #include <gtest/gtest.h>
 
 #include <algorithm>
@@ -30,7 +29,6 @@
 #include <numeric>
 #include <vector>
 
-#include <MemoryUtils.h>
 #include <android/binder_status.h>
 #include <nnapi/Result.h>
 #include <nnapi/SharedMemory.h>
@@ -43,6 +41,10 @@
 #include "Utils.h"
 #include "VtsHalNeuralnetworks.h"
 
+#ifdef __ANDROID__
+#include <android/sync.h>
+#endif  // __ANDROID__
+
 namespace aidl::android::hardware::neuralnetworks::vts::functional {
 
 namespace nn = ::android::nn;
@@ -58,25 +60,66 @@
     bool measureTiming;
     OutputType outputType;
     MemoryType memoryType;
+    bool reusable;
     // `reportSkipping` indicates if a test should print an info message in case
     // it is skipped. The field is set to true by default and is set to false in
     // quantization coupling tests to suppress skipping a test
     bool reportSkipping;
-    TestConfig(Executor executor, bool measureTiming, OutputType outputType, MemoryType memoryType)
-        : executor(executor),
-          measureTiming(measureTiming),
-          outputType(outputType),
-          memoryType(memoryType),
-          reportSkipping(true) {}
+    // `useConfig` indicates if a test should use execute*WithConfig functions for the execution.
+    bool useConfig;
     TestConfig(Executor executor, bool measureTiming, OutputType outputType, MemoryType memoryType,
-               bool reportSkipping)
+               bool reusable)
         : executor(executor),
           measureTiming(measureTiming),
           outputType(outputType),
           memoryType(memoryType),
-          reportSkipping(reportSkipping) {}
+          reusable(reusable),
+          reportSkipping(true),
+          useConfig(false) {}
+    TestConfig(Executor executor, bool measureTiming, OutputType outputType, MemoryType memoryType,
+               bool reusable, bool reportSkipping)
+        : executor(executor),
+          measureTiming(measureTiming),
+          outputType(outputType),
+          memoryType(memoryType),
+          reusable(reusable),
+          reportSkipping(reportSkipping),
+          useConfig(false) {}
+    TestConfig(Executor executor, bool measureTiming, OutputType outputType, MemoryType memoryType,
+               bool reusable, bool reportSkipping, bool useConfig)
+        : executor(executor),
+          measureTiming(measureTiming),
+          outputType(outputType),
+          memoryType(memoryType),
+          reusable(reusable),
+          reportSkipping(reportSkipping),
+          useConfig(useConfig) {}
 };
 
+std::string toString(OutputType type) {
+    switch (type) {
+        case OutputType::FULLY_SPECIFIED:
+            return "FULLY_SPECIFIED";
+        case OutputType::UNSPECIFIED:
+            return "UNSPECIFIED";
+        case OutputType::INSUFFICIENT:
+            return "INSUFFICIENT";
+        case OutputType::MISSED_DEADLINE:
+            return "MISSED_DEADLINE";
+    }
+}
+
+std::string toString(const TestConfig& config) {
+    std::stringstream ss;
+    ss << "TestConfig{.executor=" << toString(config.executor)
+       << ", .measureTiming=" << (config.measureTiming ? "true" : "false")
+       << ", .outputType=" << toString(config.outputType)
+       << ", .memoryType=" << toString(config.memoryType)
+       << ", .reusable=" << (config.reusable ? "true" : "false")
+       << ", .useConfig=" << (config.useConfig ? "true" : "false") << "}";
+    return ss.str();
+}
+
 enum class IOType { INPUT, OUTPUT };
 
 class DeviceMemoryAllocator {
@@ -240,10 +283,14 @@
 }  // namespace
 
 void waitForSyncFence(int syncFd) {
-    constexpr int kInfiniteTimeout = -1;
     ASSERT_GT(syncFd, 0);
+#ifdef __ANDROID__
+    constexpr int kInfiniteTimeout = -1;
     int r = sync_wait(syncFd, kInfiniteTimeout);
     ASSERT_GE(r, 0);
+#else   // __ANDROID__
+    LOG(FATAL) << "waitForSyncFence not supported on host";
+#endif  // __ANDROID__
 }
 
 Model createModel(const TestModel& testModel) {
@@ -558,209 +605,269 @@
         loopTimeoutDurationNs = 1 * kMillisecond;
     }
 
-    ErrorStatus executionStatus;
-    std::vector<OutputShape> outputShapes;
-    Timing timing = kNoTiming;
-    switch (testConfig.executor) {
-        case Executor::SYNC: {
-            SCOPED_TRACE("synchronous");
+    std::shared_ptr<IExecution> execution;
+    if (testConfig.reusable) {
+        const auto ret = preparedModel->createReusableExecution(
+                request, {testConfig.measureTiming, loopTimeoutDurationNs, {}, {}}, &execution);
+        ASSERT_TRUE(ret.isOk()) << static_cast<nn::ErrorStatus>(ret.getServiceSpecificError());
+        ASSERT_NE(nullptr, execution.get());
+    }
 
-            ExecutionResult executionResult;
-            // execute
-            const auto ret = preparedModel->executeSynchronously(request, testConfig.measureTiming,
-                                                                 kNoDeadline, loopTimeoutDurationNs,
-                                                                 &executionResult);
-            ASSERT_TRUE(ret.isOk() || ret.getExceptionCode() == EX_SERVICE_SPECIFIC)
-                    << ret.getDescription();
-            if (ret.isOk()) {
-                executionStatus = executionResult.outputSufficientSize
-                                          ? ErrorStatus::NONE
-                                          : ErrorStatus::OUTPUT_INSUFFICIENT_SIZE;
-                outputShapes = std::move(executionResult.outputShapes);
-                timing = executionResult.timing;
-            } else {
-                executionStatus = static_cast<ErrorStatus>(ret.getServiceSpecificError());
-            }
-            break;
-        }
-        case Executor::BURST: {
-            SCOPED_TRACE("burst");
+    const auto executeAndCheckResults = [&preparedModel, &execution, &testConfig, &testModel,
+                                         &context, &request, loopTimeoutDurationNs, skipped]() {
+        ErrorStatus executionStatus;
+        std::vector<OutputShape> outputShapes;
+        Timing timing = kNoTiming;
+        switch (testConfig.executor) {
+            case Executor::SYNC: {
+                SCOPED_TRACE("synchronous");
 
-            // create burst
-            std::shared_ptr<IBurst> burst;
-            auto ret = preparedModel->configureExecutionBurst(&burst);
-            ASSERT_TRUE(ret.isOk()) << ret.getDescription();
-            ASSERT_NE(nullptr, burst.get());
-
-            // associate a unique slot with each memory pool
-            int64_t currentSlot = 0;
-            std::vector<int64_t> slots;
-            slots.reserve(request.pools.size());
-            for (const auto& pool : request.pools) {
-                if (pool.getTag() == RequestMemoryPool::Tag::pool) {
-                    slots.push_back(currentSlot++);
+                ExecutionResult executionResult;
+                // execute
+                ::ndk::ScopedAStatus ret;
+                if (testConfig.reusable) {
+                    ret = execution->executeSynchronously(kNoDeadline, &executionResult);
+                } else if (testConfig.useConfig) {
+                    ret = preparedModel->executeSynchronouslyWithConfig(
+                            request, {testConfig.measureTiming, loopTimeoutDurationNs, {}, {}},
+                            kNoDeadline, &executionResult);
                 } else {
-                    EXPECT_EQ(pool.getTag(), RequestMemoryPool::Tag::token);
-                    slots.push_back(-1);
+                    ret = preparedModel->executeSynchronously(request, testConfig.measureTiming,
+                                                              kNoDeadline, loopTimeoutDurationNs,
+                                                              &executionResult);
                 }
+                ASSERT_TRUE(ret.isOk() || ret.getExceptionCode() == EX_SERVICE_SPECIFIC)
+                        << ret.getDescription();
+                if (ret.isOk()) {
+                    executionStatus = executionResult.outputSufficientSize
+                                              ? ErrorStatus::NONE
+                                              : ErrorStatus::OUTPUT_INSUFFICIENT_SIZE;
+                    outputShapes = std::move(executionResult.outputShapes);
+                    timing = executionResult.timing;
+                } else {
+                    executionStatus = static_cast<ErrorStatus>(ret.getServiceSpecificError());
+                }
+                break;
             }
+            case Executor::BURST: {
+                SCOPED_TRACE("burst");
 
-            ExecutionResult executionResult;
-            // execute
-            ret = burst->executeSynchronously(request, slots, testConfig.measureTiming, kNoDeadline,
-                                              loopTimeoutDurationNs, &executionResult);
-            ASSERT_TRUE(ret.isOk() || ret.getExceptionCode() == EX_SERVICE_SPECIFIC)
-                    << ret.getDescription();
-            if (ret.isOk()) {
-                executionStatus = executionResult.outputSufficientSize
-                                          ? ErrorStatus::NONE
-                                          : ErrorStatus::OUTPUT_INSUFFICIENT_SIZE;
-                outputShapes = std::move(executionResult.outputShapes);
-                timing = executionResult.timing;
-            } else {
-                executionStatus = static_cast<ErrorStatus>(ret.getServiceSpecificError());
-            }
-
-            // Mark each slot as unused after the execution. This is unnecessary because the burst
-            // is freed after this scope ends, but this is here to test the functionality.
-            for (int64_t slot : slots) {
-                ret = burst->releaseMemoryResource(slot);
+                // create burst
+                std::shared_ptr<IBurst> burst;
+                auto ret = preparedModel->configureExecutionBurst(&burst);
                 ASSERT_TRUE(ret.isOk()) << ret.getDescription();
-            }
+                ASSERT_NE(nullptr, burst.get());
 
-            break;
-        }
-        case Executor::FENCED: {
-            SCOPED_TRACE("fenced");
-            ErrorStatus result = ErrorStatus::NONE;
-            FencedExecutionResult executionResult;
-            auto ret = preparedModel->executeFenced(request, {}, testConfig.measureTiming,
-                                                    kNoDeadline, loopTimeoutDurationNs, kNoDuration,
-                                                    &executionResult);
-            ASSERT_TRUE(ret.isOk() || ret.getExceptionCode() == EX_SERVICE_SPECIFIC)
-                    << ret.getDescription();
-            if (!ret.isOk()) {
-                result = static_cast<ErrorStatus>(ret.getServiceSpecificError());
-                executionStatus = result;
-            } else if (executionResult.syncFence.get() != -1) {
-                std::vector<ndk::ScopedFileDescriptor> waitFor;
-                auto dupFd = dup(executionResult.syncFence.get());
-                ASSERT_NE(dupFd, -1);
-                waitFor.emplace_back(dupFd);
-                // If a sync fence is returned, try start another run waiting for the sync fence.
-                ret = preparedModel->executeFenced(request, waitFor, testConfig.measureTiming,
-                                                   kNoDeadline, loopTimeoutDurationNs, kNoDuration,
-                                                   &executionResult);
-                ASSERT_TRUE(ret.isOk());
-                waitForSyncFence(executionResult.syncFence.get());
-            }
-            if (result == ErrorStatus::NONE) {
-                ASSERT_NE(executionResult.callback, nullptr);
-                Timing timingFenced;
-                auto ret = executionResult.callback->getExecutionInfo(&timing, &timingFenced,
-                                                                      &executionStatus);
-                ASSERT_TRUE(ret.isOk());
-            }
-            break;
-        }
-        default: {
-            FAIL() << "Unsupported execution mode for AIDL interface.";
-        }
-    }
-
-    if (testConfig.outputType != OutputType::FULLY_SPECIFIED &&
-        executionStatus == ErrorStatus::GENERAL_FAILURE) {
-        if (skipped != nullptr) {
-            *skipped = true;
-        }
-        if (!testConfig.reportSkipping) {
-            return;
-        }
-        LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
-                     "execute model that it does not support.";
-        std::cout << "[          ]   Early termination of test because vendor service cannot "
-                     "execute model that it does not support."
-                  << std::endl;
-        GTEST_SKIP();
-    }
-    if (!testConfig.measureTiming) {
-        EXPECT_EQ(timing, kNoTiming);
-    } else {
-        if (timing.timeOnDeviceNs != -1 && timing.timeInDriverNs != -1) {
-            EXPECT_LE(timing.timeOnDeviceNs, timing.timeInDriverNs);
-        }
-    }
-
-    switch (testConfig.outputType) {
-        case OutputType::FULLY_SPECIFIED:
-            if (testConfig.executor == Executor::FENCED && hasZeroSizedOutput(testModel)) {
-                // Executor::FENCED does not support zero-sized output.
-                ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, executionStatus);
-                return;
-            }
-            // If the model output operands are fully specified, outputShapes must be either
-            // either empty, or have the same number of elements as the number of outputs.
-            ASSERT_EQ(ErrorStatus::NONE, executionStatus);
-            ASSERT_TRUE(outputShapes.size() == 0 ||
-                        outputShapes.size() == testModel.main.outputIndexes.size());
-            break;
-        case OutputType::UNSPECIFIED:
-            if (testConfig.executor == Executor::FENCED) {
-                // For Executor::FENCED, the output shape must be fully specified.
-                ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, executionStatus);
-                return;
-            }
-            // If the model output operands are not fully specified, outputShapes must have
-            // the same number of elements as the number of outputs.
-            ASSERT_EQ(ErrorStatus::NONE, executionStatus);
-            ASSERT_EQ(outputShapes.size(), testModel.main.outputIndexes.size());
-            break;
-        case OutputType::INSUFFICIENT:
-            if (testConfig.executor == Executor::FENCED) {
-                // For Executor::FENCED, the output shape must be fully specified.
-                ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, executionStatus);
-                return;
-            }
-            ASSERT_EQ(ErrorStatus::OUTPUT_INSUFFICIENT_SIZE, executionStatus);
-            ASSERT_EQ(outputShapes.size(), testModel.main.outputIndexes.size());
-            // Check that all returned output dimensions are at least as fully specified as the
-            // union of the information about the corresponding operand in the model and in the
-            // request. In this test, all model outputs have known rank with all dimensions
-            // unspecified, and no dimensional information is provided in the request.
-            for (uint32_t i = 0; i < outputShapes.size(); i++) {
-                ASSERT_EQ(outputShapes[i].isSufficient, i != kInsufficientOutputIndex);
-                const auto& actual = outputShapes[i].dimensions;
-                const auto& golden =
-                        testModel.main.operands[testModel.main.outputIndexes[i]].dimensions;
-                ASSERT_EQ(actual.size(), golden.size());
-                for (uint32_t j = 0; j < actual.size(); j++) {
-                    if (actual[j] == 0) continue;
-                    EXPECT_EQ(actual[j], golden[j]) << "index: " << j;
+                // associate a unique slot with each memory pool
+                constexpr int64_t kIgnoreSlot = -1;
+                int64_t currentSlot = 0;
+                std::vector<int64_t> slots;
+                slots.reserve(request.pools.size());
+                for (const auto& pool : request.pools) {
+                    if (pool.getTag() == RequestMemoryPool::Tag::pool) {
+                        slots.push_back(currentSlot++);
+                    } else {
+                        EXPECT_EQ(pool.getTag(), RequestMemoryPool::Tag::token);
+                        slots.push_back(kIgnoreSlot);
+                    }
                 }
+
+                ExecutionResult executionResult;
+                // execute
+                if (testConfig.useConfig) {
+                    ret = burst->executeSynchronouslyWithConfig(
+                            request, slots,
+                            {testConfig.measureTiming, loopTimeoutDurationNs, {}, {}}, kNoDeadline,
+                            &executionResult);
+                } else {
+                    ret = burst->executeSynchronously(request, slots, testConfig.measureTiming,
+                                                      kNoDeadline, loopTimeoutDurationNs,
+                                                      &executionResult);
+                }
+                ASSERT_TRUE(ret.isOk() || ret.getExceptionCode() == EX_SERVICE_SPECIFIC)
+                        << ret.getDescription();
+                if (ret.isOk()) {
+                    executionStatus = executionResult.outputSufficientSize
+                                              ? ErrorStatus::NONE
+                                              : ErrorStatus::OUTPUT_INSUFFICIENT_SIZE;
+                    outputShapes = std::move(executionResult.outputShapes);
+                    timing = executionResult.timing;
+                } else {
+                    executionStatus = static_cast<ErrorStatus>(ret.getServiceSpecificError());
+                }
+
+                // Mark each slot as unused after the execution. This is unnecessary because the
+                // burst is freed after this scope ends, but this is here to test the functionality.
+                for (int64_t slot : slots) {
+                    if (slot != kIgnoreSlot) {
+                        ret = burst->releaseMemoryResource(slot);
+                        ASSERT_TRUE(ret.isOk()) << ret.getDescription();
+                    }
+                }
+
+                break;
             }
-            return;
-        case OutputType::MISSED_DEADLINE:
-            ASSERT_TRUE(executionStatus == ErrorStatus::MISSED_DEADLINE_TRANSIENT ||
-                        executionStatus == ErrorStatus::MISSED_DEADLINE_PERSISTENT)
-                    << "executionStatus = " << executionStatus;
-            return;
+            case Executor::FENCED: {
+                SCOPED_TRACE("fenced");
+                ErrorStatus result = ErrorStatus::NONE;
+                FencedExecutionResult executionResult;
+                ::ndk::ScopedAStatus ret;
+                if (testConfig.reusable) {
+                    ret = execution->executeFenced({}, kNoDeadline, kNoDuration, &executionResult);
+                } else if (testConfig.useConfig) {
+                    ret = preparedModel->executeFencedWithConfig(
+                            request, {}, {testConfig.measureTiming, loopTimeoutDurationNs, {}, {}},
+                            kNoDeadline, kNoDuration, &executionResult);
+                } else {
+                    ret = preparedModel->executeFenced(request, {}, testConfig.measureTiming,
+                                                       kNoDeadline, loopTimeoutDurationNs,
+                                                       kNoDuration, &executionResult);
+                }
+                ASSERT_TRUE(ret.isOk() || ret.getExceptionCode() == EX_SERVICE_SPECIFIC)
+                        << ret.getDescription();
+                if (!ret.isOk()) {
+                    result = static_cast<ErrorStatus>(ret.getServiceSpecificError());
+                    executionStatus = result;
+                } else if (executionResult.syncFence.get() != -1) {
+                    std::vector<ndk::ScopedFileDescriptor> waitFor;
+                    auto dupFd = dup(executionResult.syncFence.get());
+                    ASSERT_NE(dupFd, -1);
+                    waitFor.emplace_back(dupFd);
+                    // If a sync fence is returned, try start another run waiting for the sync
+                    // fence.
+                    if (testConfig.reusable) {
+                        ret = execution->executeFenced(waitFor, kNoDeadline, kNoDuration,
+                                                       &executionResult);
+                    } else if (testConfig.useConfig) {
+                        ret = preparedModel->executeFencedWithConfig(
+                                request, waitFor,
+                                {testConfig.measureTiming, loopTimeoutDurationNs, {}, {}},
+                                kNoDeadline, kNoDuration, &executionResult);
+                    } else {
+                        ret = preparedModel->executeFenced(
+                                request, waitFor, testConfig.measureTiming, kNoDeadline,
+                                loopTimeoutDurationNs, kNoDuration, &executionResult);
+                    }
+                    ASSERT_TRUE(ret.isOk());
+                    waitForSyncFence(executionResult.syncFence.get());
+                }
+                if (result == ErrorStatus::NONE) {
+                    ASSERT_NE(executionResult.callback, nullptr);
+                    Timing timingFenced;
+                    auto ret = executionResult.callback->getExecutionInfo(&timing, &timingFenced,
+                                                                          &executionStatus);
+                    ASSERT_TRUE(ret.isOk());
+                }
+                break;
+            }
+            default: {
+                FAIL() << "Unsupported execution mode for AIDL interface.";
+            }
+        }
+
+        if (testConfig.outputType != OutputType::FULLY_SPECIFIED &&
+            executionStatus == ErrorStatus::GENERAL_FAILURE) {
+            if (skipped != nullptr) {
+                *skipped = true;
+            }
+            if (!testConfig.reportSkipping) {
+                return;
+            }
+            LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
+                         "execute model that it does not support.";
+            std::cout << "[          ]   Early termination of test because vendor service cannot "
+                         "execute model that it does not support."
+                      << std::endl;
+            GTEST_SKIP();
+        }
+        if (!testConfig.measureTiming) {
+            EXPECT_EQ(timing, kNoTiming);
+        } else {
+            if (timing.timeOnDeviceNs != -1 && timing.timeInDriverNs != -1) {
+                EXPECT_LE(timing.timeOnDeviceNs, timing.timeInDriverNs);
+            }
+        }
+
+        switch (testConfig.outputType) {
+            case OutputType::FULLY_SPECIFIED:
+                if (testConfig.executor == Executor::FENCED && hasZeroSizedOutput(testModel)) {
+                    // Executor::FENCED does not support zero-sized output.
+                    ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, executionStatus);
+                    return;
+                }
+                // If the model output operands are fully specified, outputShapes must be either
+                // either empty, or have the same number of elements as the number of outputs.
+                ASSERT_EQ(ErrorStatus::NONE, executionStatus);
+                ASSERT_TRUE(outputShapes.size() == 0 ||
+                            outputShapes.size() == testModel.main.outputIndexes.size());
+                break;
+            case OutputType::UNSPECIFIED:
+                if (testConfig.executor == Executor::FENCED) {
+                    // For Executor::FENCED, the output shape must be fully specified.
+                    ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, executionStatus);
+                    return;
+                }
+                // If the model output operands are not fully specified, outputShapes must have
+                // the same number of elements as the number of outputs.
+                ASSERT_EQ(ErrorStatus::NONE, executionStatus);
+                ASSERT_EQ(outputShapes.size(), testModel.main.outputIndexes.size());
+                break;
+            case OutputType::INSUFFICIENT:
+                if (testConfig.executor == Executor::FENCED) {
+                    // For Executor::FENCED, the output shape must be fully specified.
+                    ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, executionStatus);
+                    return;
+                }
+                ASSERT_EQ(ErrorStatus::OUTPUT_INSUFFICIENT_SIZE, executionStatus);
+                ASSERT_EQ(outputShapes.size(), testModel.main.outputIndexes.size());
+                // Check that all returned output dimensions are at least as fully specified as the
+                // union of the information about the corresponding operand in the model and in the
+                // request. In this test, all model outputs have known rank with all dimensions
+                // unspecified, and no dimensional information is provided in the request.
+                for (uint32_t i = 0; i < outputShapes.size(); i++) {
+                    ASSERT_EQ(outputShapes[i].isSufficient, i != kInsufficientOutputIndex);
+                    const auto& actual = outputShapes[i].dimensions;
+                    const auto& golden =
+                            testModel.main.operands[testModel.main.outputIndexes[i]].dimensions;
+                    ASSERT_EQ(actual.size(), golden.size());
+                    for (uint32_t j = 0; j < actual.size(); j++) {
+                        if (actual[j] == 0) continue;
+                        EXPECT_EQ(actual[j], golden[j]) << "index: " << j;
+                    }
+                }
+                return;
+            case OutputType::MISSED_DEADLINE:
+                ASSERT_TRUE(executionStatus == ErrorStatus::MISSED_DEADLINE_TRANSIENT ||
+                            executionStatus == ErrorStatus::MISSED_DEADLINE_PERSISTENT)
+                        << "executionStatus = " << executionStatus;
+                return;
+        }
+
+        // Go through all outputs, check returned output shapes.
+        for (uint32_t i = 0; i < outputShapes.size(); i++) {
+            EXPECT_TRUE(outputShapes[i].isSufficient);
+            const auto& expect =
+                    testModel.main.operands[testModel.main.outputIndexes[i]].dimensions;
+            const auto unsignedActual = nn::toUnsigned(outputShapes[i].dimensions);
+            ASSERT_TRUE(unsignedActual.has_value());
+            const std::vector<uint32_t>& actual = unsignedActual.value();
+            EXPECT_EQ(expect, actual);
+        }
+
+        // Retrieve execution results.
+        const std::vector<TestBuffer> outputs = context.getOutputBuffers(testModel, request);
+
+        // We want "close-enough" results.
+        checkResults(testModel, outputs);
+    };
+
+    executeAndCheckResults();
+
+    // For reusable execution tests, run the execution twice.
+    if (testConfig.reusable) {
+        SCOPED_TRACE("Second execution");
+        executeAndCheckResults();
     }
-
-    // Go through all outputs, check returned output shapes.
-    for (uint32_t i = 0; i < outputShapes.size(); i++) {
-        EXPECT_TRUE(outputShapes[i].isSufficient);
-        const auto& expect = testModel.main.operands[testModel.main.outputIndexes[i]].dimensions;
-        const auto unsignedActual = nn::toUnsigned(outputShapes[i].dimensions);
-        ASSERT_TRUE(unsignedActual.has_value());
-        const std::vector<uint32_t>& actual = unsignedActual.value();
-        EXPECT_EQ(expect, actual);
-    }
-
-    // Retrieve execution results.
-    const std::vector<TestBuffer> outputs = context.getOutputBuffers(testModel, request);
-
-    // We want "close-enough" results.
-    checkResults(testModel, outputs);
 }
 
 void EvaluatePreparedModel(const std::shared_ptr<IDevice>& device,
@@ -770,6 +877,15 @@
     std::vector<bool> measureTimingList;
     std::vector<Executor> executorList;
     std::vector<MemoryType> memoryTypeList;
+    std::vector<bool> reusableList = {false};
+    std::vector<bool> useConfigList = {false};
+
+    int deviceVersion;
+    ASSERT_TRUE(device->getInterfaceVersion(&deviceVersion).isOk());
+    if (deviceVersion >= kMinAidlLevelForFL8) {
+        reusableList.push_back(true);
+        useConfigList.push_back(true);
+    }
 
     switch (testKind) {
         case TestKind::GENERAL: {
@@ -788,7 +904,11 @@
             outputTypesList = {OutputType::FULLY_SPECIFIED};
             measureTimingList = {false};
             executorList = {Executor::SYNC, Executor::BURST, Executor::FENCED};
+#ifdef __ANDROID__
             memoryTypeList = {MemoryType::BLOB_AHWB, MemoryType::DEVICE};
+#else   // __ANDROID__
+            memoryTypeList = {MemoryType::DEVICE};  // BLOB_AHWB is not supported on the host.
+#endif  // __ANDROID__
         } break;
         case TestKind::FENCED_COMPUTE: {
             outputTypesList = {OutputType::FULLY_SPECIFIED};
@@ -812,8 +932,16 @@
         for (const bool measureTiming : measureTimingList) {
             for (const Executor executor : executorList) {
                 for (const MemoryType memoryType : memoryTypeList) {
-                    const TestConfig testConfig(executor, measureTiming, outputType, memoryType);
-                    EvaluatePreparedModel(device, preparedModel, testModel, testConfig);
+                    for (const bool reusable : reusableList) {
+                        for (const bool useConfig : useConfigList) {
+                            if ((useConfig || executor == Executor::BURST) && reusable) continue;
+                            const TestConfig testConfig(executor, measureTiming, outputType,
+                                                        memoryType, reusable,
+                                                        /*reportSkipping=*/true, useConfig);
+                            SCOPED_TRACE(toString(testConfig));
+                            EvaluatePreparedModel(device, preparedModel, testModel, testConfig);
+                        }
+                    }
                 }
             }
         }
@@ -833,7 +961,7 @@
         for (const bool measureTiming : measureTimingList) {
             for (const Executor executor : executorList) {
                 const TestConfig testConfig(executor, measureTiming, outputType, MemoryType::ASHMEM,
-                                            /*reportSkipping=*/false);
+                                            /*reusable=*/false, /*reportSkipping=*/false);
                 bool baseSkipped = false;
                 EvaluatePreparedModel(device, preparedModel, testModel, testConfig, &baseSkipped);
                 bool coupledSkipped = false;
@@ -871,6 +999,13 @@
             createPreparedModel(device, model, &preparedModel);
             if (preparedModel == nullptr) return;
             EvaluatePreparedModel(device, preparedModel, testModel, testKind);
+            int32_t deviceVersion;
+            ASSERT_TRUE(device->getInterfaceVersion(&deviceVersion).isOk());
+            if (deviceVersion >= kMinAidlLevelForFL8) {
+                createPreparedModel(device, model, &preparedModel, /*reportSkipping*/ true,
+                                    /*useConfig*/ true);
+                EvaluatePreparedModel(device, preparedModel, testModel, testKind);
+            }
         } break;
         case TestKind::QUANTIZATION_COUPLING: {
             ASSERT_TRUE(testModel.hasQuant8CoupledOperands());
diff --git a/neuralnetworks/aidl/vts/functional/MemoryDomainTests.cpp b/neuralnetworks/aidl/vts/functional/MemoryDomainTests.cpp
index 1819699..f8341b1 100644
--- a/neuralnetworks/aidl/vts/functional/MemoryDomainTests.cpp
+++ b/neuralnetworks/aidl/vts/functional/MemoryDomainTests.cpp
@@ -17,6 +17,7 @@
 #define LOG_TAG "neuralnetworks_aidl_hal_test"
 
 #include <aidl/android/hardware/graphics/common/PixelFormat.h>
+#include <aidl/android/hardware/neuralnetworks/IPreparedModel.h>
 #include <android-base/logging.h>
 #include <android/binder_auto_utils.h>
 #include <android/binder_interface_utils.h>
@@ -28,12 +29,11 @@
 #include <Utils.h>
 #include <nnapi/SharedMemory.h>
 #include <nnapi/hal/aidl/Conversions.h>
+#include <nnapi/hal/aidl/HalInterfaces.h>
 #include <nnapi/hal/aidl/Utils.h>
 
-#include "AidlHalInterfaces.h"
 #include "Callbacks.h"
 #include "GeneratedTestHarness.h"
-#include "MemoryUtils.h"
 #include "Utils.h"
 #include "VtsHalNeuralnetworks.h"
 
@@ -191,7 +191,7 @@
 }
 
 // A placeholder invalid IPreparedModel class for MemoryDomainAllocateTest.InvalidPreparedModel
-class InvalidPreparedModel : public BnPreparedModel {
+class InvalidPreparedModel final : public IPreparedModel {
   public:
     ndk::ScopedAStatus executeSynchronously(const Request&, bool, int64_t, int64_t,
                                             ExecutionResult*) override {
@@ -204,10 +204,37 @@
         return ndk::ScopedAStatus::fromServiceSpecificError(
                 static_cast<int32_t>(ErrorStatus::GENERAL_FAILURE));
     }
+    ndk::ScopedAStatus executeSynchronouslyWithConfig(const Request&, const ExecutionConfig&,
+                                                      int64_t, ExecutionResult*) override {
+        return ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(ErrorStatus::GENERAL_FAILURE));
+    }
+    ndk::ScopedAStatus executeFencedWithConfig(const Request&,
+                                               const std::vector<ndk::ScopedFileDescriptor>&,
+                                               const ExecutionConfig&, int64_t, int64_t,
+                                               FencedExecutionResult*) override {
+        return ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(ErrorStatus::GENERAL_FAILURE));
+    }
     ndk::ScopedAStatus configureExecutionBurst(std::shared_ptr<IBurst>*) override {
         return ndk::ScopedAStatus::fromServiceSpecificError(
                 static_cast<int32_t>(ErrorStatus::GENERAL_FAILURE));
     }
+    ndk::ScopedAStatus createReusableExecution(const aidl_hal::Request&, const ExecutionConfig&,
+                                               std::shared_ptr<aidl_hal::IExecution>*) override {
+        return ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(ErrorStatus::GENERAL_FAILURE));
+    }
+    ndk::ScopedAStatus getInterfaceVersion(int32_t* /*interfaceVersion*/) {
+        return ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(ErrorStatus::GENERAL_FAILURE));
+    }
+    ndk::ScopedAStatus getInterfaceHash(std::string* /*interfaceHash*/) {
+        return ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(ErrorStatus::GENERAL_FAILURE));
+    }
+    ndk::SpAIBinder asBinder() override { return ::ndk::SpAIBinder{}; }
+    bool isRemote() override { return true; }
 };
 
 template <typename... Args>
diff --git a/neuralnetworks/aidl/vts/functional/Utils.cpp b/neuralnetworks/aidl/vts/functional/Utils.cpp
index 325a436..1bc76f2 100644
--- a/neuralnetworks/aidl/vts/functional/Utils.cpp
+++ b/neuralnetworks/aidl/vts/functional/Utils.cpp
@@ -21,18 +21,20 @@
 #include <aidl/android/hardware/neuralnetworks/OperandType.h>
 #include <android-base/logging.h>
 #include <android/binder_status.h>
-#include <android/hardware_buffer.h>
 
 #include <sys/mman.h>
 #include <iostream>
 #include <limits>
 #include <numeric>
 
-#include <MemoryUtils.h>
 #include <nnapi/SharedMemory.h>
 #include <nnapi/hal/aidl/Conversions.h>
 #include <nnapi/hal/aidl/Utils.h>
 
+#ifdef __ANDROID__
+#include <android/hardware_buffer.h>
+#endif  // __ANDROID__
+
 namespace aidl::android::hardware::neuralnetworks {
 
 using test_helper::TestBuffer;
@@ -140,7 +142,8 @@
     return ahwb->mIsValid ? std::move(ahwb) : nullptr;
 }
 
-void TestBlobAHWB::initialize(uint32_t size) {
+void TestBlobAHWB::initialize([[maybe_unused]] uint32_t size) {
+#ifdef __ANDROID__
     mIsValid = false;
     ASSERT_GT(size, 0);
     const auto usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
@@ -164,6 +167,9 @@
     mAidlMemory = utils::convert(mMemory).value();
 
     mIsValid = true;
+#else   // __ANDROID__
+    LOG(FATAL) << "TestBlobAHWB::initialize not supported on host";
+#endif  // __ANDROID__
 }
 
 std::string gtestCompliantName(std::string name) {
@@ -177,6 +183,17 @@
     return os << toString(errorStatus);
 }
 
+std::string toString(MemoryType type) {
+    switch (type) {
+        case MemoryType::ASHMEM:
+            return "ASHMEM";
+        case MemoryType::BLOB_AHWB:
+            return "BLOB_AHWB";
+        case MemoryType::DEVICE:
+            return "DEVICE";
+    }
+}
+
 Request ExecutionContext::createRequest(const TestModel& testModel, MemoryType memoryType) {
     CHECK(memoryType == MemoryType::ASHMEM || memoryType == MemoryType::BLOB_AHWB);
 
diff --git a/neuralnetworks/aidl/vts/functional/Utils.h b/neuralnetworks/aidl/vts/functional/Utils.h
index ca81418..ccb0778 100644
--- a/neuralnetworks/aidl/vts/functional/Utils.h
+++ b/neuralnetworks/aidl/vts/functional/Utils.h
@@ -18,10 +18,10 @@
 #define ANDROID_HARDWARE_NEURALNETWORKS_AIDL_UTILS_H
 
 #include <android-base/logging.h>
-#include <android/hardware_buffer.h>
 #include <gtest/gtest.h>
 
 #include <algorithm>
+#include <array>
 #include <iosfwd>
 #include <string>
 #include <utility>
@@ -48,6 +48,7 @@
 inline constexpr int64_t kOmittedTimeoutDuration = -1;
 inline constexpr int64_t kNoDuration = -1;
 inline const std::vector<uint8_t> kEmptyCacheToken(IDevice::BYTE_SIZE_OF_CACHE_TOKEN);
+inline const std::array<uint8_t, IDevice::BYTE_SIZE_OF_CACHE_TOKEN> kEmptyCacheTokenArray{};
 
 // Returns the amount of space needed to store a value of the specified type.
 //
@@ -111,6 +112,8 @@
 
 enum class MemoryType { ASHMEM, BLOB_AHWB, DEVICE };
 
+std::string toString(MemoryType type);
+
 // Manages the lifetime of memory resources used in an execution.
 class ExecutionContext {
     DISALLOW_COPY_AND_ASSIGN(ExecutionContext);
diff --git a/neuralnetworks/aidl/vts/functional/ValidateModel.cpp b/neuralnetworks/aidl/vts/functional/ValidateModel.cpp
index afb3b71..060434e 100644
--- a/neuralnetworks/aidl/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/aidl/vts/functional/ValidateModel.cpp
@@ -77,6 +77,28 @@
     ASSERT_EQ(nullptr, preparedModel.get());
 }
 
+static void validatePrepareModelWithConfig(const std::shared_ptr<IDevice>& device,
+                                           const std::string& message, const Model& model,
+                                           ExecutionPreference preference, Priority priority) {
+    SCOPED_TRACE(message + " [prepareModelWithConfig]");
+
+    std::shared_ptr<PreparedModelCallback> preparedModelCallback =
+            ndk::SharedRefBase::make<PreparedModelCallback>();
+    const auto prepareLaunchStatus = device->prepareModelWithConfig(
+            model, {preference, priority, kNoDeadline, {}, {}, kEmptyCacheTokenArray, {}, {}},
+            preparedModelCallback);
+    ASSERT_FALSE(prepareLaunchStatus.isOk());
+    ASSERT_EQ(prepareLaunchStatus.getExceptionCode(), EX_SERVICE_SPECIFIC);
+    ASSERT_EQ(static_cast<ErrorStatus>(prepareLaunchStatus.getServiceSpecificError()),
+              ErrorStatus::INVALID_ARGUMENT);
+
+    preparedModelCallback->wait();
+    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
+    ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, prepareReturnStatus);
+    std::shared_ptr<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel();
+    ASSERT_EQ(nullptr, preparedModel.get());
+}
+
 static bool validExecutionPreference(ExecutionPreference preference) {
     return preference == ExecutionPreference::LOW_POWER ||
            preference == ExecutionPreference::FAST_SINGLE_ANSWER ||
@@ -103,6 +125,13 @@
     }
 
     validatePrepareModel(device, message, model, preference, priority);
+
+    int32_t aidlVersion;
+    ASSERT_TRUE(device->getInterfaceVersion(&aidlVersion).isOk());
+    if (aidlVersion >= kMinAidlLevelForFL8) {
+        // prepareModelWithConfig must satisfy all requirements enforced by prepareModel.
+        validatePrepareModelWithConfig(device, message, model, preference, priority);
+    }
 }
 
 static uint32_t addOperand(Model* model) {
@@ -1321,8 +1350,8 @@
 
 void validateModel(const std::shared_ptr<IDevice>& device, const Model& model) {
     const auto numberOfConsumers =
-            nn::countNumberOfConsumers(model.main.operands.size(),
-                                       nn::unvalidatedConvert(model.main.operations).value())
+            countNumberOfConsumers(model.main.operands.size(),
+                                   nn::unvalidatedConvert(model.main.operations).value())
                     .value();
     mutateExecutionOrderTest(device, model, numberOfConsumers);
     mutateOperandTypeTest(device, model);
diff --git a/neuralnetworks/aidl/vts/functional/ValidateRequest.cpp b/neuralnetworks/aidl/vts/functional/ValidateRequest.cpp
index 29e2471..d749841 100644
--- a/neuralnetworks/aidl/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/aidl/vts/functional/ValidateRequest.cpp
@@ -36,6 +36,51 @@
 
 ///////////////////////// UTILITY FUNCTIONS /////////////////////////
 
+// Test request validation with reusable execution.
+static void validateReusableExecution(const std::shared_ptr<IPreparedModel>& preparedModel,
+                                      const std::string& message, const Request& request,
+                                      bool measure) {
+    // createReusableExecution
+    std::shared_ptr<IExecution> execution;
+    {
+        SCOPED_TRACE(message + " [createReusableExecution]");
+        const auto createStatus = preparedModel->createReusableExecution(
+                request, {measure, kOmittedTimeoutDuration, {}, {}}, &execution);
+        if (!createStatus.isOk()) {
+            ASSERT_EQ(createStatus.getExceptionCode(), EX_SERVICE_SPECIFIC);
+            ASSERT_EQ(static_cast<ErrorStatus>(createStatus.getServiceSpecificError()),
+                      ErrorStatus::INVALID_ARGUMENT);
+            ASSERT_EQ(nullptr, execution);
+            return;
+        } else {
+            ASSERT_NE(nullptr, execution);
+        }
+    }
+
+    // synchronous
+    {
+        SCOPED_TRACE(message + " [executeSynchronously]");
+        ExecutionResult executionResult;
+        const auto executeStatus = execution->executeSynchronously(kNoDeadline, &executionResult);
+        ASSERT_FALSE(executeStatus.isOk());
+        ASSERT_EQ(executeStatus.getExceptionCode(), EX_SERVICE_SPECIFIC);
+        ASSERT_EQ(static_cast<ErrorStatus>(executeStatus.getServiceSpecificError()),
+                  ErrorStatus::INVALID_ARGUMENT);
+    }
+
+    // fenced
+    {
+        SCOPED_TRACE(message + " [executeFenced]");
+        FencedExecutionResult executionResult;
+        const auto executeStatus =
+                execution->executeFenced({}, kNoDeadline, kNoDuration, &executionResult);
+        ASSERT_FALSE(executeStatus.isOk());
+        ASSERT_EQ(executeStatus.getExceptionCode(), EX_SERVICE_SPECIFIC);
+        ASSERT_EQ(static_cast<ErrorStatus>(executeStatus.getServiceSpecificError()),
+                  ErrorStatus::INVALID_ARGUMENT);
+    }
+}
+
 // Primary validation function. This function will take a valid request, apply a
 // mutation to it to invalidate the request, then pass it to interface calls
 // that use the request.
@@ -101,6 +146,63 @@
         ASSERT_EQ(static_cast<ErrorStatus>(executeStatus.getServiceSpecificError()),
                   ErrorStatus::INVALID_ARGUMENT);
     }
+
+    int32_t aidlVersion;
+    ASSERT_TRUE(preparedModel->getInterfaceVersion(&aidlVersion).isOk());
+    if (aidlVersion < kMinAidlLevelForFL8) {
+        return;
+    }
+
+    // validate reusable execution
+    validateReusableExecution(preparedModel, message, request, measure);
+
+    // synchronous with empty hints
+    {
+        SCOPED_TRACE(message + " [executeSynchronouslyWithConfig]");
+        ExecutionResult executionResult;
+        const auto executeStatus = preparedModel->executeSynchronouslyWithConfig(
+                request, {measure, kOmittedTimeoutDuration, {}, {}}, kNoDeadline, &executionResult);
+        ASSERT_FALSE(executeStatus.isOk());
+        ASSERT_EQ(executeStatus.getExceptionCode(), EX_SERVICE_SPECIFIC);
+        ASSERT_EQ(static_cast<ErrorStatus>(executeStatus.getServiceSpecificError()),
+                  ErrorStatus::INVALID_ARGUMENT);
+    }
+
+    // fenced with empty hints
+    {
+        SCOPED_TRACE(message + " [executeFencedWithConfig]");
+        FencedExecutionResult executionResult;
+        const auto executeStatus = preparedModel->executeFencedWithConfig(
+                request, {}, {false, kOmittedTimeoutDuration, {}, {}}, kNoDeadline, kNoDuration,
+                &executionResult);
+        ASSERT_FALSE(executeStatus.isOk());
+        ASSERT_EQ(executeStatus.getExceptionCode(), EX_SERVICE_SPECIFIC);
+        ASSERT_EQ(static_cast<ErrorStatus>(executeStatus.getServiceSpecificError()),
+                  ErrorStatus::INVALID_ARGUMENT);
+    }
+
+    // burst with empty hints
+    {
+        SCOPED_TRACE(message + " [burst executeSynchronouslyWithConfig]");
+
+        // create burst
+        std::shared_ptr<IBurst> burst;
+        auto ret = preparedModel->configureExecutionBurst(&burst);
+        ASSERT_TRUE(ret.isOk()) << ret.getDescription();
+        ASSERT_NE(nullptr, burst.get());
+
+        // use -1 for all memory identifier tokens
+        const std::vector<int64_t> slots(request.pools.size(), -1);
+
+        ExecutionResult executionResult;
+        const auto executeStatus = burst->executeSynchronouslyWithConfig(
+                request, slots, {measure, kOmittedTimeoutDuration, {}, {}}, kNoDeadline,
+                &executionResult);
+        ASSERT_FALSE(executeStatus.isOk());
+        ASSERT_EQ(executeStatus.getExceptionCode(), EX_SERVICE_SPECIFIC);
+        ASSERT_EQ(static_cast<ErrorStatus>(executeStatus.getServiceSpecificError()),
+                  ErrorStatus::INVALID_ARGUMENT);
+    }
 }
 
 std::shared_ptr<IBurst> createBurst(const std::shared_ptr<IPreparedModel>& preparedModel) {
diff --git a/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.cpp
index c417356..bf87f15 100644
--- a/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.cpp
+++ b/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.cpp
@@ -15,6 +15,7 @@
  */
 
 #define LOG_TAG "neuralnetworks_aidl_hal_test"
+
 #include "VtsHalNeuralnetworks.h"
 
 #include <android-base/logging.h>
@@ -28,20 +29,27 @@
 #include <utility>
 
 #include <TestHarness.h>
-#include <aidl/Vintf.h>
 #include <nnapi/hal/aidl/Conversions.h>
 
 #include "Callbacks.h"
 #include "GeneratedTestHarness.h"
 #include "Utils.h"
 
+#ifdef __ANDROID__
+#include <aidl/Vintf.h>
+#else  // __ANDROID__
+#include <CanonicalDevice.h>
+#include <nnapi/hal/aidl/Adapter.h>
+#endif  // __ANDROID__
+
 namespace aidl::android::hardware::neuralnetworks::vts::functional {
 
 using implementation::PreparedModelCallback;
 
 // internal helper function
 void createPreparedModel(const std::shared_ptr<IDevice>& device, const Model& model,
-                         std::shared_ptr<IPreparedModel>* preparedModel, bool reportSkipping) {
+                         std::shared_ptr<IPreparedModel>* preparedModel, bool reportSkipping,
+                         bool useConfig) {
     ASSERT_NE(nullptr, preparedModel);
     *preparedModel = nullptr;
 
@@ -56,11 +64,25 @@
     // launch prepare model
     const std::shared_ptr<PreparedModelCallback> preparedModelCallback =
             ndk::SharedRefBase::make<PreparedModelCallback>();
-    const auto prepareLaunchStatus =
-            device->prepareModel(model, ExecutionPreference::FAST_SINGLE_ANSWER, kDefaultPriority,
-                                 kNoDeadline, {}, {}, kEmptyCacheToken, preparedModelCallback);
-    ASSERT_TRUE(prepareLaunchStatus.isOk()) << prepareLaunchStatus.getDescription();
-
+    if (useConfig) {
+        const auto prepareLaunchStatus =
+                device->prepareModelWithConfig(model,
+                                               {ExecutionPreference::FAST_SINGLE_ANSWER,
+                                                kDefaultPriority,
+                                                kNoDeadline,
+                                                {},
+                                                {},
+                                                kEmptyCacheTokenArray,
+                                                {},
+                                                {}},
+                                               preparedModelCallback);
+        ASSERT_TRUE(prepareLaunchStatus.isOk()) << prepareLaunchStatus.getDescription();
+    } else {
+        const auto prepareLaunchStatus = device->prepareModel(
+                model, ExecutionPreference::FAST_SINGLE_ANSWER, kDefaultPriority, kNoDeadline, {},
+                {}, kEmptyCacheToken, preparedModelCallback);
+        ASSERT_TRUE(prepareLaunchStatus.isOk()) << prepareLaunchStatus.getDescription();
+    }
     // retrieve prepared model
     preparedModelCallback->wait();
     const ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
@@ -96,6 +118,7 @@
     ASSERT_TRUE(deviceIsResponsive);
 }
 
+#ifdef __ANDROID__
 static NamedDevice makeNamedDevice(const std::string& name) {
     ndk::SpAIBinder binder(AServiceManager_waitForService(name.c_str()));
     return {name, IDevice::fromBinder(binder)};
@@ -112,6 +135,14 @@
     std::transform(names.begin(), names.end(), std::back_inserter(namedDevices), makeNamedDevice);
     return namedDevices;
 }
+#else   // __ANDROID__
+static std::vector<NamedDevice> getNamedDevicesImpl() {
+    const std::string name = "nnapi-sample";
+    auto device = std::make_shared<const ::android::nn::sample::Device>(name);
+    auto aidlDevice = adapter::adapt(device);
+    return {{name, aidlDevice}};
+}
+#endif  // __ANDROID__
 
 const std::vector<NamedDevice>& getNamedDevices() {
     const static std::vector<NamedDevice> devices = getNamedDevicesImpl();
diff --git a/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.h
index 4312d3a..00d705c 100644
--- a/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.h
+++ b/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.h
@@ -30,6 +30,8 @@
 using NamedDevice = Named<std::shared_ptr<IDevice>>;
 using NeuralNetworksAidlTestParam = NamedDevice;
 
+constexpr int kMinAidlLevelForFL8 = 4;
+
 class NeuralNetworksAidlTest : public testing::TestWithParam<NeuralNetworksAidlTestParam> {
   protected:
     void SetUp() override;
@@ -49,8 +51,8 @@
 // Create an IPreparedModel object. If the model cannot be prepared,
 // "preparedModel" will be nullptr instead.
 void createPreparedModel(const std::shared_ptr<IDevice>& device, const Model& model,
-                         std::shared_ptr<IPreparedModel>* preparedModel,
-                         bool reportSkipping = true);
+                         std::shared_ptr<IPreparedModel>* preparedModel, bool reportSkipping = true,
+                         bool useConfig = false);
 
 enum class Executor { SYNC, BURST, FENCED };
 
diff --git a/neuralnetworks/utils/OWNERS b/neuralnetworks/utils/OWNERS
deleted file mode 100644
index e4feee3..0000000
--- a/neuralnetworks/utils/OWNERS
+++ /dev/null
@@ -1,11 +0,0 @@
-# Neuralnetworks team
-butlermichael@google.com
-dgross@google.com
-galarragas@google.com
-jeanluc@google.com
-levp@google.com
-miaowang@google.com
-pszczepaniak@google.com
-slavash@google.com
-vddang@google.com
-xusongw@google.com
diff --git a/neuralnetworks/utils/README.md b/neuralnetworks/utils/README.md
index 87b3f9f..ffad6ee 100644
--- a/neuralnetworks/utils/README.md
+++ b/neuralnetworks/utils/README.md
@@ -44,7 +44,7 @@
 EXPECT_EQ(versionedBefore, versionedAfter);
 ```
 
-The `convert` functions operate only on types that used in a HIDL method call directly. The
+The `convert` functions operate only on types that are used in a HIDL method call directly. The
 `unvalidatedConvert` functions operate on types that are either used in a HIDL method call directly
 (i.e., not as a nested class) or used in a subsequent version of the NN HAL. Prefer using `convert`
 over `unvalidatedConvert`.
diff --git a/neuralnetworks/utils/adapter/Android.bp b/neuralnetworks/utils/adapter/Android.bp
deleted file mode 100644
index d073106..0000000
--- a/neuralnetworks/utils/adapter/Android.bp
+++ /dev/null
@@ -1,46 +0,0 @@
-//
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-package {
-    // See: http://go/android-license-faq
-    // A large-scale-change added 'default_applicable_licenses' to import
-    // all of the 'license_kinds' from "hardware_interfaces_license"
-    // to get the below license kinds:
-    //   SPDX-license-identifier-Apache-2.0
-    default_applicable_licenses: ["hardware_interfaces_license"],
-}
-
-cc_library_static {
-    name: "neuralnetworks_utils_hal_adapter",
-    defaults: ["neuralnetworks_utils_defaults"],
-    srcs: ["src/*"],
-    local_include_dirs: ["include/nnapi/hal"],
-    export_include_dirs: ["include"],
-    static_libs: [
-        "neuralnetworks_types",
-        "neuralnetworks_utils_hal_1_0",
-        "neuralnetworks_utils_hal_1_1",
-        "neuralnetworks_utils_hal_1_2",
-        "neuralnetworks_utils_hal_1_3",
-    ],
-    shared_libs: [
-        "android.hardware.neuralnetworks@1.0",
-        "android.hardware.neuralnetworks@1.1",
-        "android.hardware.neuralnetworks@1.2",
-        "android.hardware.neuralnetworks@1.3",
-        "libfmq",
-    ],
-}
diff --git a/neuralnetworks/utils/adapter/aidl/Android.bp b/neuralnetworks/utils/adapter/aidl/Android.bp
new file mode 100644
index 0000000..8269a3d
--- /dev/null
+++ b/neuralnetworks/utils/adapter/aidl/Android.bp
@@ -0,0 +1,42 @@
+//
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_library_static {
+    name: "neuralnetworks_utils_hal_adapter_aidl",
+    defaults: [
+        "neuralnetworks_use_latest_utils_hal_aidl",
+        "neuralnetworks_utils_defaults",
+    ],
+    srcs: ["src/*"],
+    local_include_dirs: ["include/nnapi/hal/aidl/"],
+    export_include_dirs: ["include"],
+    static_libs: [
+        "neuralnetworks_types",
+        "neuralnetworks_utils_hal_common",
+    ],
+    shared_libs: [
+        "libbinder_ndk",
+    ],
+}
diff --git a/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Adapter.h b/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Adapter.h
new file mode 100644
index 0000000..80ed41d
--- /dev/null
+++ b/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Adapter.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_AIDL_ADAPTER_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_AIDL_ADAPTER_H
+
+#include <aidl/android/hardware/neuralnetworks/BnDevice.h>
+#include <nnapi/IDevice.h>
+#include <nnapi/Types.h>
+
+#include <functional>
+#include <memory>
+
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on AIDL interface
+// lifetimes across processes and for protecting asynchronous calls across AIDL.
+
+namespace aidl::android::hardware::neuralnetworks::adapter {
+
+/**
+ * A self-contained unit of work to be executed.
+ */
+using Task = std::function<void()>;
+
+/**
+ * A type-erased executor which executes a task asynchronously.
+ *
+ * This executor is also provided an optional deadline for when the caller expects is the upper
+ * bound for the amount of time to complete the task. If needed, the Executor can retrieve the
+ * Application ID (Android User ID) by calling AIBinder_getCallingUid in android/binder_ibinder.h.
+ */
+using Executor = std::function<void(Task, ::android::nn::OptionalTimePoint)>;
+
+/**
+ * Adapt an NNAPI canonical interface object to a AIDL NN HAL interface object.
+ *
+ * @param device NNAPI canonical IDevice interface object to be adapted.
+ * @param executor Type-erased executor to handle executing tasks asynchronously.
+ * @return AIDL NN HAL IDevice interface object.
+ */
+std::shared_ptr<BnDevice> adapt(::android::nn::SharedDevice device, Executor executor);
+
+/**
+ * Adapt an NNAPI canonical interface object to a AIDL NN HAL interface object.
+ *
+ * This function uses a default executor, which will execute tasks from a detached thread.
+ *
+ * @param device NNAPI canonical IDevice interface object to be adapted.
+ * @return AIDL NN HAL IDevice interface object.
+ */
+std::shared_ptr<BnDevice> adapt(::android::nn::SharedDevice device);
+
+}  // namespace aidl::android::hardware::neuralnetworks::adapter
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_AIDL_ADAPTER_H
diff --git a/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Buffer.h b/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Buffer.h
new file mode 100644
index 0000000..701e43e
--- /dev/null
+++ b/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Buffer.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_AIDL_BUFFER_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_AIDL_BUFFER_H
+
+#include <aidl/android/hardware/neuralnetworks/BnBuffer.h>
+#include <aidl/android/hardware/neuralnetworks/Memory.h>
+#include <android/binder_auto_utils.h>
+#include <nnapi/IBuffer.h>
+
+#include <memory>
+#include <vector>
+
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on AIDL interface
+// lifetimes across processes and for protecting asynchronous calls across AIDL.
+
+namespace aidl::android::hardware::neuralnetworks::adapter {
+
+// Class that adapts nn::IBuffer to BnBuffer.
+class Buffer : public BnBuffer {
+  public:
+    explicit Buffer(::android::nn::SharedBuffer buffer);
+
+    ndk::ScopedAStatus copyFrom(const Memory& src, const std::vector<int32_t>& dimensions) override;
+    ndk::ScopedAStatus copyTo(const Memory& dst) override;
+
+  private:
+    const ::android::nn::SharedBuffer kBuffer;
+};
+
+}  // namespace aidl::android::hardware::neuralnetworks::adapter
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_AIDL_BUFFER_H
diff --git a/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Burst.h b/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Burst.h
new file mode 100644
index 0000000..8d42e2f
--- /dev/null
+++ b/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Burst.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_AIDL_BURST_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_AIDL_BURST_H
+
+#include <aidl/android/hardware/neuralnetworks/BnBurst.h>
+#include <aidl/android/hardware/neuralnetworks/ExecutionResult.h>
+#include <aidl/android/hardware/neuralnetworks/Request.h>
+#include <android-base/thread_annotations.h>
+#include <android/binder_auto_utils.h>
+#include <nnapi/IBurst.h>
+#include <nnapi/Types.h>
+
+#include <memory>
+#include <mutex>
+#include <unordered_map>
+#include <vector>
+
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on AIDL interface
+// lifetimes across processes and for protecting asynchronous calls across AIDL.
+
+namespace aidl::android::hardware::neuralnetworks::adapter {
+
+// Class that adapts nn::Burst to BnBurst.
+class Burst : public BnBurst {
+  public:
+    // Precondition: burst != nullptr
+    explicit Burst(::android::nn::SharedBurst burst);
+
+    ndk::ScopedAStatus executeSynchronously(const Request& request,
+                                            const std::vector<int64_t>& memoryIdentifierTokens,
+                                            bool measureTiming, int64_t deadlineNs,
+                                            int64_t loopTimeoutDurationNs,
+                                            ExecutionResult* executionResult) override;
+    ndk::ScopedAStatus executeSynchronouslyWithConfig(
+            const Request& request, const std::vector<int64_t>& memoryIdentifierTokens,
+            const ExecutionConfig& config, int64_t deadlineNs,
+            ExecutionResult* executionResult) override;
+
+    ndk::ScopedAStatus releaseMemoryResource(int64_t memoryIdentifierToken) override;
+
+    class ThreadSafeMemoryCache {
+      public:
+        using Value =
+                std::pair<::android::nn::SharedMemory, ::android::nn::IBurst::OptionalCacheHold>;
+
+        Value add(int64_t token, const ::android::nn::SharedMemory& memory,
+                  const ::android::nn::IBurst& burst) const;
+        void remove(int64_t token) const;
+
+      private:
+        mutable std::mutex mMutex;
+        mutable std::unordered_map<int64_t, Value> mCache GUARDED_BY(mMutex);
+    };
+
+  private:
+    const ::android::nn::SharedBurst kBurst;
+    const ThreadSafeMemoryCache kMemoryCache;
+};
+
+}  // namespace aidl::android::hardware::neuralnetworks::adapter
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_AIDL_BURST_H
diff --git a/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Device.h b/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Device.h
new file mode 100644
index 0000000..c94f270
--- /dev/null
+++ b/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Device.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_AIDL_DEVICE_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_AIDL_DEVICE_H
+
+#include "nnapi/hal/aidl/Adapter.h"
+
+#include <aidl/android/hardware/neuralnetworks/BnDevice.h>
+#include <aidl/android/hardware/neuralnetworks/BufferDesc.h>
+#include <aidl/android/hardware/neuralnetworks/BufferRole.h>
+#include <aidl/android/hardware/neuralnetworks/Capabilities.h>
+#include <aidl/android/hardware/neuralnetworks/DeviceBuffer.h>
+#include <aidl/android/hardware/neuralnetworks/DeviceType.h>
+#include <aidl/android/hardware/neuralnetworks/ExecutionPreference.h>
+#include <aidl/android/hardware/neuralnetworks/Extension.h>
+#include <aidl/android/hardware/neuralnetworks/IPreparedModelCallback.h>
+#include <aidl/android/hardware/neuralnetworks/IPreparedModelParcel.h>
+#include <aidl/android/hardware/neuralnetworks/Model.h>
+#include <aidl/android/hardware/neuralnetworks/NumberOfCacheFiles.h>
+#include <aidl/android/hardware/neuralnetworks/PrepareModelConfig.h>
+#include <aidl/android/hardware/neuralnetworks/Priority.h>
+#include <android/binder_auto_utils.h>
+#include <nnapi/IDevice.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on AIDL interface
+// lifetimes across processes and for protecting asynchronous calls across AIDL.
+
+namespace aidl::android::hardware::neuralnetworks::adapter {
+
+// Class that adapts nn::IDevice to BnDevice.
+class Device : public BnDevice {
+  public:
+    Device(::android::nn::SharedDevice device, Executor executor);
+
+    ndk::ScopedAStatus allocate(const BufferDesc& desc,
+                                const std::vector<IPreparedModelParcel>& preparedModels,
+                                const std::vector<BufferRole>& inputRoles,
+                                const std::vector<BufferRole>& outputRoles,
+                                DeviceBuffer* buffer) override;
+    ndk::ScopedAStatus getCapabilities(Capabilities* capabilities) override;
+    ndk::ScopedAStatus getNumberOfCacheFilesNeeded(NumberOfCacheFiles* numberOfCacheFiles) override;
+    ndk::ScopedAStatus getSupportedExtensions(std::vector<Extension>* extensions) override;
+    ndk::ScopedAStatus getSupportedOperations(const Model& model,
+                                              std::vector<bool>* supported) override;
+    ndk::ScopedAStatus getType(DeviceType* deviceType) override;
+    ndk::ScopedAStatus getVersionString(std::string* version) override;
+    ndk::ScopedAStatus prepareModel(
+            const Model& model, ExecutionPreference preference, Priority priority,
+            int64_t deadlineNs, const std::vector<ndk::ScopedFileDescriptor>& modelCache,
+            const std::vector<ndk::ScopedFileDescriptor>& dataCache,
+            const std::vector<uint8_t>& token,
+            const std::shared_ptr<IPreparedModelCallback>& callback) override;
+    ndk::ScopedAStatus prepareModelFromCache(
+            int64_t deadlineNs, const std::vector<ndk::ScopedFileDescriptor>& modelCache,
+            const std::vector<ndk::ScopedFileDescriptor>& dataCache,
+            const std::vector<uint8_t>& token,
+            const std::shared_ptr<IPreparedModelCallback>& callback) override;
+    ndk::ScopedAStatus prepareModelWithConfig(
+            const Model& model, const PrepareModelConfig& config,
+            const std::shared_ptr<IPreparedModelCallback>& callback) override;
+
+  protected:
+    const ::android::nn::SharedDevice kDevice;
+    const Executor kExecutor;
+};
+
+}  // namespace aidl::android::hardware::neuralnetworks::adapter
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_AIDL_DEVICE_H
diff --git a/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Execution.h b/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Execution.h
new file mode 100644
index 0000000..6a9ac57
--- /dev/null
+++ b/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/Execution.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.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_AIDL_EXECUTION_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_AIDL_EXECUTION_H
+
+#include "nnapi/hal/aidl/Adapter.h"
+
+#include <aidl/android/hardware/neuralnetworks/BnExecution.h>
+#include <aidl/android/hardware/neuralnetworks/ExecutionResult.h>
+#include <aidl/android/hardware/neuralnetworks/FencedExecutionResult.h>
+#include <aidl/android/hardware/neuralnetworks/IExecution.h>
+#include <aidl/android/hardware/neuralnetworks/Request.h>
+#include <android/binder_auto_utils.h>
+#include <nnapi/IExecution.h>
+#include <nnapi/Types.h>
+
+#include <memory>
+#include <vector>
+
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on AIDL interface
+// lifetimes across processes and for protecting asynchronous calls across AIDL.
+
+namespace aidl::android::hardware::neuralnetworks::adapter {
+
+// Class that adapts nn::IExecution to BnExecution.
+class Execution : public BnExecution {
+  public:
+    explicit Execution(::android::nn::SharedExecution execution);
+
+    ndk::ScopedAStatus executeSynchronously(int64_t deadlineNs,
+                                            ExecutionResult* executionResult) override;
+    ndk::ScopedAStatus executeFenced(const std::vector<ndk::ScopedFileDescriptor>& waitFor,
+                                     int64_t deadlineNs, int64_t durationNs,
+                                     FencedExecutionResult* fencedExecutionResult) override;
+
+  protected:
+    const ::android::nn::SharedExecution kExecution;
+};
+
+}  // namespace aidl::android::hardware::neuralnetworks::adapter
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_AIDL_EXECUTION_H
diff --git a/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/PreparedModel.h b/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/PreparedModel.h
new file mode 100644
index 0000000..d1359d6
--- /dev/null
+++ b/neuralnetworks/utils/adapter/aidl/include/nnapi/hal/aidl/PreparedModel.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_AIDL_PREPARED_MDOEL_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_AIDL_PREPARED_MDOEL_H
+
+#include "nnapi/hal/aidl/Adapter.h"
+
+#include <aidl/android/hardware/neuralnetworks/BnPreparedModel.h>
+#include <aidl/android/hardware/neuralnetworks/ExecutionResult.h>
+#include <aidl/android/hardware/neuralnetworks/FencedExecutionResult.h>
+#include <aidl/android/hardware/neuralnetworks/IBurst.h>
+#include <aidl/android/hardware/neuralnetworks/IExecution.h>
+#include <aidl/android/hardware/neuralnetworks/Request.h>
+#include <android/binder_auto_utils.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Types.h>
+
+#include <memory>
+#include <vector>
+
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on AIDL interface
+// lifetimes across processes and for protecting asynchronous calls across AIDL.
+
+namespace aidl::android::hardware::neuralnetworks::adapter {
+
+// Class that adapts nn::IPreparedModel to BnPreparedModel.
+class PreparedModel : public BnPreparedModel {
+  public:
+    explicit PreparedModel(::android::nn::SharedPreparedModel preparedModel);
+
+    ndk::ScopedAStatus executeSynchronously(const Request& request, bool measureTiming,
+                                            int64_t deadlineNs, int64_t loopTimeoutDurationNs,
+                                            ExecutionResult* executionResult) override;
+    ndk::ScopedAStatus executeFenced(const Request& request,
+                                     const std::vector<ndk::ScopedFileDescriptor>& waitFor,
+                                     bool measureTiming, int64_t deadlineNs,
+                                     int64_t loopTimeoutDurationNs, int64_t durationNs,
+                                     FencedExecutionResult* executionResult) override;
+    ndk::ScopedAStatus configureExecutionBurst(std::shared_ptr<IBurst>* burst) override;
+    ndk::ScopedAStatus createReusableExecution(const Request& request,
+                                               const ExecutionConfig& config,
+                                               std::shared_ptr<IExecution>* execution) override;
+    ndk::ScopedAStatus executeSynchronouslyWithConfig(const Request& request,
+                                                      const ExecutionConfig& config,
+                                                      int64_t deadlineNs,
+                                                      ExecutionResult* executionResult) override;
+    ndk::ScopedAStatus executeFencedWithConfig(
+            const Request& request, const std::vector<ndk::ScopedFileDescriptor>& waitFor,
+            const ExecutionConfig& config, int64_t deadlineNs, int64_t durationNs,
+            FencedExecutionResult* executionResult) override;
+
+    ::android::nn::SharedPreparedModel getUnderlyingPreparedModel() const;
+
+  protected:
+    const ::android::nn::SharedPreparedModel kPreparedModel;
+};
+
+}  // namespace aidl::android::hardware::neuralnetworks::adapter
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_AIDL_PREPARED_MDOEL_H
diff --git a/neuralnetworks/utils/adapter/aidl/src/Adapter.cpp b/neuralnetworks/utils/adapter/aidl/src/Adapter.cpp
new file mode 100644
index 0000000..d0b56e8
--- /dev/null
+++ b/neuralnetworks/utils/adapter/aidl/src/Adapter.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Adapter.h"
+
+#include "Device.h"
+
+#include <aidl/android/hardware/neuralnetworks/BnDevice.h>
+#include <android/binder_interface_utils.h>
+#include <nnapi/IDevice.h>
+#include <nnapi/Types.h>
+
+#include <functional>
+#include <memory>
+#include <thread>
+
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on AIDL interface
+// lifetimes across processes and for protecting asynchronous calls across AIDL.
+
+namespace aidl::android::hardware::neuralnetworks::adapter {
+
+std::shared_ptr<BnDevice> adapt(::android::nn::SharedDevice device, Executor executor) {
+    return ndk::SharedRefBase::make<Device>(std::move(device), std::move(executor));
+}
+
+std::shared_ptr<BnDevice> adapt(::android::nn::SharedDevice device) {
+    Executor defaultExecutor = [](Task task, ::android::nn::OptionalTimePoint /*deadline*/) {
+        std::thread(std::move(task)).detach();
+    };
+    return adapt(std::move(device), std::move(defaultExecutor));
+}
+
+}  // namespace aidl::android::hardware::neuralnetworks::adapter
diff --git a/neuralnetworks/utils/adapter/aidl/src/Buffer.cpp b/neuralnetworks/utils/adapter/aidl/src/Buffer.cpp
new file mode 100644
index 0000000..c15ab65
--- /dev/null
+++ b/neuralnetworks/utils/adapter/aidl/src/Buffer.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Buffer.h"
+
+#include <aidl/android/hardware/neuralnetworks/BnBuffer.h>
+#include <aidl/android/hardware/neuralnetworks/Memory.h>
+#include <android-base/logging.h>
+#include <android/binder_auto_utils.h>
+#include <nnapi/IBuffer.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/aidl/Conversions.h>
+
+namespace aidl::android::hardware::neuralnetworks::adapter {
+namespace {
+
+template <typename Type>
+auto convertInput(const Type& object) -> decltype(nn::convert(std::declval<Type>())) {
+    auto result = nn::convert(object);
+    if (!result.has_value()) {
+        result.error().code = nn::ErrorStatus::INVALID_ARGUMENT;
+    }
+    return result;
+}
+
+nn::GeneralResult<std::vector<uint32_t>> inputToUnsigned(const std::vector<int32_t>& dims) {
+    auto result = nn::toUnsigned(dims);
+    if (!result.has_value()) {
+        result.error().code = nn::ErrorStatus::INVALID_ARGUMENT;
+    }
+    return result;
+}
+
+nn::GeneralResult<void> copyTo(const nn::IBuffer& buffer, const Memory& dst) {
+    const auto nnDst = NN_TRY(convertInput(dst));
+    return buffer.copyTo(nnDst);
+}
+
+nn::GeneralResult<void> copyFrom(const nn::IBuffer& buffer, const Memory& src,
+                                 const std::vector<int32_t>& dimensions) {
+    const auto nnSrc = NN_TRY(convertInput(src));
+    const auto nnDims = NN_TRY(inputToUnsigned(dimensions));
+    return buffer.copyFrom(nnSrc, nnDims);
+}
+
+}  // namespace
+
+Buffer::Buffer(nn::SharedBuffer buffer) : kBuffer(std::move(buffer)) {
+    CHECK(kBuffer != nullptr);
+}
+
+ndk::ScopedAStatus Buffer::copyTo(const Memory& dst) {
+    const auto result = adapter::copyTo(*kBuffer, dst);
+    if (!result.has_value()) {
+        const auto& [message, code] = result.error();
+        const auto aidlCode = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
+        return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+                static_cast<int32_t>(aidlCode), message.c_str());
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Buffer::copyFrom(const Memory& src, const std::vector<int32_t>& dimensions) {
+    const auto result = adapter::copyFrom(*kBuffer, src, dimensions);
+    if (!result.has_value()) {
+        const auto& [message, code] = result.error();
+        const auto aidlCode = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
+        return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+                static_cast<int32_t>(aidlCode), message.c_str());
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace aidl::android::hardware::neuralnetworks::adapter
diff --git a/neuralnetworks/utils/adapter/aidl/src/Burst.cpp b/neuralnetworks/utils/adapter/aidl/src/Burst.cpp
new file mode 100644
index 0000000..a4a80fa
--- /dev/null
+++ b/neuralnetworks/utils/adapter/aidl/src/Burst.cpp
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Burst.h"
+
+#include <android-base/logging.h>
+#include <android-base/thread_annotations.h>
+#include <android/binder_auto_utils.h>
+#include <nnapi/IBurst.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/Validation.h>
+#include <nnapi/hal/aidl/Conversions.h>
+#include <nnapi/hal/aidl/Utils.h>
+
+#include <algorithm>
+#include <chrono>
+#include <memory>
+#include <mutex>
+#include <unordered_map>
+#include <utility>
+#include <variant>
+
+namespace aidl::android::hardware::neuralnetworks::adapter {
+namespace {
+
+using Value = Burst::ThreadSafeMemoryCache::Value;
+
+template <typename Type>
+auto convertInput(const Type& object) -> decltype(nn::convert(std::declval<Type>())) {
+    auto result = nn::convert(object);
+    if (!result.has_value()) {
+        result.error().code = nn::ErrorStatus::INVALID_ARGUMENT;
+    }
+    return result;
+}
+
+nn::Duration makeDuration(int64_t durationNs) {
+    return nn::Duration(std::chrono::nanoseconds(durationNs));
+}
+
+nn::GeneralResult<nn::OptionalDuration> makeOptionalDuration(int64_t durationNs) {
+    if (durationNs < -1) {
+        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid duration " << durationNs;
+    }
+    return durationNs < 0 ? nn::OptionalDuration{} : makeDuration(durationNs);
+}
+
+nn::GeneralResult<nn::OptionalTimePoint> makeOptionalTimePoint(int64_t durationNs) {
+    if (durationNs < -1) {
+        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid time point " << durationNs;
+    }
+    return durationNs < 0 ? nn::OptionalTimePoint{} : nn::TimePoint(makeDuration(durationNs));
+}
+
+std::vector<nn::IBurst::OptionalCacheHold> ensureAllMemoriesAreCached(
+        nn::Request* request, const std::vector<int64_t>& memoryIdentifierTokens,
+        const nn::IBurst& burst, const Burst::ThreadSafeMemoryCache& cache) {
+    std::vector<nn::IBurst::OptionalCacheHold> holds;
+    holds.reserve(memoryIdentifierTokens.size());
+
+    for (size_t i = 0; i < memoryIdentifierTokens.size(); ++i) {
+        const auto& pool = request->pools[i];
+        const auto token = memoryIdentifierTokens[i];
+        constexpr int64_t kNoToken = -1;
+        if (token == kNoToken || !std::holds_alternative<nn::SharedMemory>(pool)) {
+            continue;
+        }
+
+        const auto& memory = std::get<nn::SharedMemory>(pool);
+        auto [storedMemory, hold] = cache.add(token, memory, burst);
+
+        request->pools[i] = std::move(storedMemory);
+        holds.push_back(std::move(hold));
+    }
+
+    return holds;
+}
+
+nn::ExecutionResult<ExecutionResult> executeSynchronously(
+        const nn::IBurst& burst, const Burst::ThreadSafeMemoryCache& cache, const Request& request,
+        const std::vector<int64_t>& memoryIdentifierTokens, bool measureTiming, int64_t deadlineNs,
+        int64_t loopTimeoutDurationNs, const std::vector<TokenValuePair>& hints,
+        const std::vector<ExtensionNameAndPrefix>& extensionNameToPrefix) {
+    if (request.pools.size() != memoryIdentifierTokens.size()) {
+        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
+               << "request.pools.size() != memoryIdentifierTokens.size()";
+    }
+    if (!std::all_of(memoryIdentifierTokens.begin(), memoryIdentifierTokens.end(),
+                     [](int64_t token) { return token >= -1; })) {
+        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid memoryIdentifierTokens";
+    }
+
+    auto nnRequest = NN_TRY(convertInput(request));
+    const auto nnMeasureTiming = measureTiming ? nn::MeasureTiming::YES : nn::MeasureTiming::NO;
+    const auto nnDeadline = NN_TRY(makeOptionalTimePoint(deadlineNs));
+    const auto nnLoopTimeoutDuration = NN_TRY(makeOptionalDuration(loopTimeoutDurationNs));
+    auto nnHints = NN_TRY(convertInput(hints));
+    auto nnExtensionNameToPrefix = NN_TRY(convertInput(extensionNameToPrefix));
+
+    const auto hold = ensureAllMemoriesAreCached(&nnRequest, memoryIdentifierTokens, burst, cache);
+
+    const auto result = burst.execute(nnRequest, nnMeasureTiming, nnDeadline, nnLoopTimeoutDuration,
+                                      nnHints, nnExtensionNameToPrefix);
+
+    if (!result.ok() && result.error().code == nn::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE) {
+        const auto& [message, code, outputShapes] = result.error();
+        return ExecutionResult{.outputSufficientSize = false,
+                               .outputShapes = utils::convert(outputShapes).value(),
+                               .timing = {.timeInDriverNs = -1, .timeOnDeviceNs = -1}};
+    }
+
+    const auto& [outputShapes, timing] = NN_TRY(result);
+    return ExecutionResult{.outputSufficientSize = true,
+                           .outputShapes = utils::convert(outputShapes).value(),
+                           .timing = utils::convert(timing).value()};
+}
+
+}  // namespace
+
+Value Burst::ThreadSafeMemoryCache::add(int64_t token, const nn::SharedMemory& memory,
+                                        const nn::IBurst& burst) const {
+    std::lock_guard guard(mMutex);
+    if (const auto it = mCache.find(token); it != mCache.end()) {
+        return it->second;
+    }
+    auto hold = burst.cacheMemory(memory);
+    auto [it, _] = mCache.emplace(token, std::make_pair(memory, std::move(hold)));
+    return it->second;
+}
+
+void Burst::ThreadSafeMemoryCache::remove(int64_t token) const {
+    std::lock_guard guard(mMutex);
+    mCache.erase(token);
+}
+
+Burst::Burst(nn::SharedBurst burst) : kBurst(std::move(burst)) {
+    CHECK(kBurst != nullptr);
+}
+
+ndk::ScopedAStatus Burst::executeSynchronously(const Request& request,
+                                               const std::vector<int64_t>& memoryIdentifierTokens,
+                                               bool measureTiming, int64_t deadlineNs,
+                                               int64_t loopTimeoutDurationNs,
+                                               ExecutionResult* executionResult) {
+    auto result =
+            adapter::executeSynchronously(*kBurst, kMemoryCache, request, memoryIdentifierTokens,
+                                          measureTiming, deadlineNs, loopTimeoutDurationNs, {}, {});
+    if (!result.has_value()) {
+        auto [message, code, _] = std::move(result).error();
+        const auto aidlCode = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
+        return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+                static_cast<int32_t>(aidlCode), message.c_str());
+    }
+    *executionResult = std::move(result).value();
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Burst::executeSynchronouslyWithConfig(
+        const Request& request, const std::vector<int64_t>& memoryIdentifierTokens,
+        const ExecutionConfig& config, int64_t deadlineNs, ExecutionResult* executionResult) {
+    auto result = adapter::executeSynchronously(
+            *kBurst, kMemoryCache, request, memoryIdentifierTokens, config.measureTiming,
+            deadlineNs, config.loopTimeoutDurationNs, config.executionHints,
+            config.extensionNameToPrefix);
+    if (!result.has_value()) {
+        auto [message, code, _] = std::move(result).error();
+        const auto aidlCode = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
+        return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+                static_cast<int32_t>(aidlCode), message.c_str());
+    }
+    *executionResult = std::move(result).value();
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Burst::releaseMemoryResource(int64_t memoryIdentifierToken) {
+    if (memoryIdentifierToken < -1) {
+        return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+                static_cast<int32_t>(ErrorStatus::INVALID_ARGUMENT),
+                "Invalid memoryIdentifierToken");
+    }
+    kMemoryCache.remove(memoryIdentifierToken);
+    return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace aidl::android::hardware::neuralnetworks::adapter
diff --git a/neuralnetworks/utils/adapter/aidl/src/Device.cpp b/neuralnetworks/utils/adapter/aidl/src/Device.cpp
new file mode 100644
index 0000000..453ec9b
--- /dev/null
+++ b/neuralnetworks/utils/adapter/aidl/src/Device.cpp
@@ -0,0 +1,337 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Device.h"
+
+#include "Adapter.h"
+#include "Buffer.h"
+#include "PreparedModel.h"
+
+#include <aidl/android/hardware/neuralnetworks/BnDevice.h>
+#include <aidl/android/hardware/neuralnetworks/BufferDesc.h>
+#include <aidl/android/hardware/neuralnetworks/BufferRole.h>
+#include <aidl/android/hardware/neuralnetworks/DeviceBuffer.h>
+#include <aidl/android/hardware/neuralnetworks/DeviceType.h>
+#include <aidl/android/hardware/neuralnetworks/ErrorStatus.h>
+#include <aidl/android/hardware/neuralnetworks/ExecutionPreference.h>
+#include <aidl/android/hardware/neuralnetworks/Extension.h>
+#include <aidl/android/hardware/neuralnetworks/IPreparedModelCallback.h>
+#include <aidl/android/hardware/neuralnetworks/IPreparedModelParcel.h>
+#include <aidl/android/hardware/neuralnetworks/Model.h>
+#include <aidl/android/hardware/neuralnetworks/NumberOfCacheFiles.h>
+#include <aidl/android/hardware/neuralnetworks/Priority.h>
+#include <android-base/logging.h>
+#include <android/binder_auto_utils.h>
+#include <android/binder_interface_utils.h>
+#include <nnapi/IDevice.h>
+#include <nnapi/Result.h>
+#include <nnapi/TypeUtils.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/aidl/Conversions.h>
+
+#include <chrono>
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace aidl::android::hardware::neuralnetworks::adapter {
+namespace {
+
+template <typename Type>
+auto convertInput(const Type& object) -> decltype(nn::convert(std::declval<Type>())) {
+    auto result = nn::convert(object);
+    if (!result.has_value()) {
+        result.error().code = nn::ErrorStatus::INVALID_ARGUMENT;
+    }
+    return result;
+}
+
+nn::Duration makeDuration(int64_t durationNs) {
+    return nn::Duration(std::chrono::nanoseconds(durationNs));
+}
+
+nn::GeneralResult<nn::OptionalTimePoint> makeOptionalTimePoint(int64_t durationNs) {
+    if (durationNs < -1) {
+        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid time point " << durationNs;
+    }
+    return durationNs < 0 ? nn::OptionalTimePoint{} : nn::TimePoint(makeDuration(durationNs));
+}
+
+nn::GeneralResult<nn::CacheToken> convertCacheToken(const std::vector<uint8_t>& token) {
+    nn::CacheToken nnToken;
+    if (token.size() != nnToken.size()) {
+        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid token";
+    }
+    std::copy(token.begin(), token.end(), nnToken.begin());
+    return nnToken;
+}
+
+nn::GeneralResult<nn::SharedPreparedModel> downcast(const IPreparedModelParcel& preparedModel) {
+    if (preparedModel.preparedModel == nullptr) {
+        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "preparedModel is nullptr";
+    }
+    if (preparedModel.preparedModel->isRemote()) {
+        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Cannot convert remote models";
+    }
+
+    // This static_cast is safe because adapter::PreparedModel is the only class that implements
+    // the IPreparedModel interface in the adapter service code.
+    const auto* casted = static_cast<const PreparedModel*>(preparedModel.preparedModel.get());
+    return casted->getUnderlyingPreparedModel();
+}
+
+nn::GeneralResult<std::vector<nn::SharedPreparedModel>> downcastAll(
+        const std::vector<IPreparedModelParcel>& preparedModels) {
+    std::vector<nn::SharedPreparedModel> canonical;
+    canonical.reserve(preparedModels.size());
+    for (const auto& preparedModel : preparedModels) {
+        canonical.push_back(NN_TRY(downcast(preparedModel)));
+    }
+    return canonical;
+}
+
+nn::GeneralResult<DeviceBuffer> allocate(const nn::IDevice& device, const BufferDesc& desc,
+                                         const std::vector<IPreparedModelParcel>& preparedModels,
+                                         const std::vector<BufferRole>& inputRoles,
+                                         const std::vector<BufferRole>& outputRoles) {
+    auto nnDesc = NN_TRY(convertInput(desc));
+    auto nnPreparedModels = NN_TRY(downcastAll(preparedModels));
+    auto nnInputRoles = NN_TRY(convertInput(inputRoles));
+    auto nnOutputRoles = NN_TRY(convertInput(outputRoles));
+
+    auto buffer = NN_TRY(device.allocate(nnDesc, nnPreparedModels, nnInputRoles, nnOutputRoles));
+    CHECK(buffer != nullptr);
+
+    const nn::Request::MemoryDomainToken token = buffer->getToken();
+    auto aidlBuffer = ndk::SharedRefBase::make<Buffer>(std::move(buffer));
+    return DeviceBuffer{.buffer = std::move(aidlBuffer), .token = static_cast<int32_t>(token)};
+}
+
+nn::GeneralResult<std::vector<bool>> getSupportedOperations(const nn::IDevice& device,
+                                                            const Model& model) {
+    const auto nnModel = NN_TRY(convertInput(model));
+    return device.getSupportedOperations(nnModel);
+}
+
+using PrepareModelResult = nn::GeneralResult<nn::SharedPreparedModel>;
+
+std::shared_ptr<PreparedModel> adaptPreparedModel(nn::SharedPreparedModel preparedModel) {
+    if (preparedModel == nullptr) {
+        return nullptr;
+    }
+    return ndk::SharedRefBase::make<PreparedModel>(std::move(preparedModel));
+}
+
+void notify(IPreparedModelCallback* callback, ErrorStatus status,
+            const std::shared_ptr<IPreparedModel>& preparedModel) {
+    if (callback != nullptr) {
+        const auto ret = callback->notify(status, preparedModel);
+        if (!ret.isOk()) {
+            LOG(ERROR) << "IPreparedModelCallback::notify failed with " << ret.getDescription();
+        }
+    }
+}
+
+void notify(IPreparedModelCallback* callback, PrepareModelResult result) {
+    if (!result.has_value()) {
+        const auto& [message, status] = result.error();
+        LOG(ERROR) << message;
+        const auto aidlCode = utils::convert(status).value_or(ErrorStatus::GENERAL_FAILURE);
+        notify(callback, aidlCode, nullptr);
+    } else {
+        auto preparedModel = std::move(result).value();
+        auto aidlPreparedModel = adaptPreparedModel(std::move(preparedModel));
+        notify(callback, ErrorStatus::NONE, std::move(aidlPreparedModel));
+    }
+}
+
+nn::GeneralResult<void> prepareModel(
+        const nn::SharedDevice& device, const Executor& executor, const Model& model,
+        ExecutionPreference preference, Priority priority, int64_t deadlineNs,
+        const std::vector<ndk::ScopedFileDescriptor>& modelCache,
+        const std::vector<ndk::ScopedFileDescriptor>& dataCache, const std::vector<uint8_t>& token,
+        const std::vector<TokenValuePair>& hints,
+        const std::vector<ExtensionNameAndPrefix>& extensionNameToPrefix,
+        const std::shared_ptr<IPreparedModelCallback>& callback) {
+    if (callback.get() == nullptr) {
+        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
+    }
+
+    auto nnModel = NN_TRY(convertInput(model));
+    const auto nnPreference = NN_TRY(convertInput(preference));
+    const auto nnPriority = NN_TRY(convertInput(priority));
+    const auto nnDeadline = NN_TRY(makeOptionalTimePoint(deadlineNs));
+    auto nnModelCache = NN_TRY(convertInput(modelCache));
+    auto nnDataCache = NN_TRY(convertInput(dataCache));
+    const auto nnToken = NN_TRY(convertCacheToken(token));
+    auto nnHints = NN_TRY(convertInput(hints));
+    auto nnExtensionNameToPrefix = NN_TRY(convertInput(extensionNameToPrefix));
+
+    Task task = [device, nnModel = std::move(nnModel), nnPreference, nnPriority, nnDeadline,
+                 nnModelCache = std::move(nnModelCache), nnDataCache = std::move(nnDataCache),
+                 nnToken, nnHints = std::move(nnHints),
+                 nnExtensionNameToPrefix = std::move(nnExtensionNameToPrefix), callback] {
+        auto result =
+                device->prepareModel(nnModel, nnPreference, nnPriority, nnDeadline, nnModelCache,
+                                     nnDataCache, nnToken, nnHints, nnExtensionNameToPrefix);
+        notify(callback.get(), std::move(result));
+    };
+    executor(std::move(task), nnDeadline);
+
+    return {};
+}
+
+nn::GeneralResult<void> prepareModelFromCache(
+        const nn::SharedDevice& device, const Executor& executor, int64_t deadlineNs,
+        const std::vector<ndk::ScopedFileDescriptor>& modelCache,
+        const std::vector<ndk::ScopedFileDescriptor>& dataCache, const std::vector<uint8_t>& token,
+        const std::shared_ptr<IPreparedModelCallback>& callback) {
+    if (callback.get() == nullptr) {
+        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
+    }
+
+    const auto nnDeadline = NN_TRY(makeOptionalTimePoint(deadlineNs));
+    auto nnModelCache = NN_TRY(convertInput(modelCache));
+    auto nnDataCache = NN_TRY(convertInput(dataCache));
+    const auto nnToken = NN_TRY(convertCacheToken(token));
+
+    auto task = [device, nnDeadline, nnModelCache = std::move(nnModelCache),
+                 nnDataCache = std::move(nnDataCache), nnToken, callback] {
+        auto result = device->prepareModelFromCache(nnDeadline, nnModelCache, nnDataCache, nnToken);
+        notify(callback.get(), std::move(result));
+    };
+    executor(std::move(task), nnDeadline);
+
+    return {};
+}
+
+}  // namespace
+
+Device::Device(::android::nn::SharedDevice device, Executor executor)
+    : kDevice(std::move(device)), kExecutor(std::move(executor)) {
+    CHECK(kDevice != nullptr);
+    CHECK(kExecutor != nullptr);
+}
+
+ndk::ScopedAStatus Device::allocate(const BufferDesc& desc,
+                                    const std::vector<IPreparedModelParcel>& preparedModels,
+                                    const std::vector<BufferRole>& inputRoles,
+                                    const std::vector<BufferRole>& outputRoles,
+                                    DeviceBuffer* buffer) {
+    auto result = adapter::allocate(*kDevice, desc, preparedModels, inputRoles, outputRoles);
+    if (!result.has_value()) {
+        const auto& [message, code] = result.error();
+        const auto aidlCode = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
+        return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+                static_cast<int32_t>(aidlCode), message.c_str());
+    }
+    *buffer = std::move(result).value();
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Device::getCapabilities(Capabilities* capabilities) {
+    *capabilities = utils::convert(kDevice->getCapabilities()).value();
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Device::getNumberOfCacheFilesNeeded(NumberOfCacheFiles* numberOfCacheFiles) {
+    const auto [numModelCache, numDataCache] = kDevice->getNumberOfCacheFilesNeeded();
+    *numberOfCacheFiles = NumberOfCacheFiles{.numModelCache = static_cast<int32_t>(numModelCache),
+                                             .numDataCache = static_cast<int32_t>(numDataCache)};
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Device::getSupportedExtensions(std::vector<Extension>* extensions) {
+    *extensions = utils::convert(kDevice->getSupportedExtensions()).value();
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Device::getSupportedOperations(const Model& model,
+                                                  std::vector<bool>* supported) {
+    auto result = adapter::getSupportedOperations(*kDevice, model);
+    if (!result.has_value()) {
+        const auto& [message, code] = result.error();
+        const auto aidlCode = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
+        return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+                static_cast<int32_t>(aidlCode), message.c_str());
+    }
+    *supported = std::move(result).value();
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Device::getType(DeviceType* deviceType) {
+    *deviceType = utils::convert(kDevice->getType()).value();
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Device::getVersionString(std::string* version) {
+    *version = kDevice->getVersionString();
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Device::prepareModel(const Model& model, ExecutionPreference preference,
+                                        Priority priority, int64_t deadlineNs,
+                                        const std::vector<ndk::ScopedFileDescriptor>& modelCache,
+                                        const std::vector<ndk::ScopedFileDescriptor>& dataCache,
+                                        const std::vector<uint8_t>& token,
+                                        const std::shared_ptr<IPreparedModelCallback>& callback) {
+    const auto result =
+            adapter::prepareModel(kDevice, kExecutor, model, preference, priority, deadlineNs,
+                                  modelCache, dataCache, token, {}, {}, callback);
+    if (!result.has_value()) {
+        const auto& [message, code] = result.error();
+        const auto aidlCode = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
+        notify(callback.get(), aidlCode, nullptr);
+        return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+                static_cast<int32_t>(aidlCode), message.c_str());
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Device::prepareModelFromCache(
+        int64_t deadlineNs, const std::vector<ndk::ScopedFileDescriptor>& modelCache,
+        const std::vector<ndk::ScopedFileDescriptor>& dataCache, const std::vector<uint8_t>& token,
+        const std::shared_ptr<IPreparedModelCallback>& callback) {
+    const auto result = adapter::prepareModelFromCache(kDevice, kExecutor, deadlineNs, modelCache,
+                                                       dataCache, token, callback);
+    if (!result.has_value()) {
+        const auto& [message, code] = result.error();
+        const auto aidlCode = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
+        notify(callback.get(), aidlCode, nullptr);
+        return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+                static_cast<int32_t>(aidlCode), message.c_str());
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Device::prepareModelWithConfig(
+        const Model& model, const PrepareModelConfig& config,
+        const std::shared_ptr<IPreparedModelCallback>& callback) {
+    const auto result = adapter::prepareModel(
+            kDevice, kExecutor, model, config.preference, config.priority, config.deadlineNs,
+            config.modelCache, config.dataCache, utils::toVec(config.cacheToken),
+            config.compilationHints, config.extensionNameToPrefix, callback);
+    if (!result.has_value()) {
+        const auto& [message, code] = result.error();
+        const auto aidlCode = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
+        notify(callback.get(), aidlCode, nullptr);
+        return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+                static_cast<int32_t>(aidlCode), message.c_str());
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace aidl::android::hardware::neuralnetworks::adapter
diff --git a/neuralnetworks/utils/adapter/aidl/src/PreparedModel.cpp b/neuralnetworks/utils/adapter/aidl/src/PreparedModel.cpp
new file mode 100644
index 0000000..790558f
--- /dev/null
+++ b/neuralnetworks/utils/adapter/aidl/src/PreparedModel.cpp
@@ -0,0 +1,371 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "PreparedModel.h"
+
+#include "Burst.h"
+#include "Execution.h"
+
+#include <aidl/android/hardware/neuralnetworks/BnFencedExecutionCallback.h>
+#include <aidl/android/hardware/neuralnetworks/BnPreparedModel.h>
+#include <aidl/android/hardware/neuralnetworks/ExecutionResult.h>
+#include <aidl/android/hardware/neuralnetworks/FencedExecutionResult.h>
+#include <aidl/android/hardware/neuralnetworks/IBurst.h>
+#include <aidl/android/hardware/neuralnetworks/Request.h>
+#include <android-base/logging.h>
+#include <android/binder_auto_utils.h>
+#include <nnapi/IExecution.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Result.h>
+#include <nnapi/SharedMemory.h>
+#include <nnapi/Types.h>
+#include <nnapi/Validation.h>
+#include <nnapi/hal/aidl/Conversions.h>
+#include <nnapi/hal/aidl/Utils.h>
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+namespace aidl::android::hardware::neuralnetworks::adapter {
+namespace {
+
+class FencedExecutionCallback : public BnFencedExecutionCallback {
+  public:
+    FencedExecutionCallback(nn::ExecuteFencedInfoCallback callback)
+        : kCallback(std::move(callback)) {}
+
+    ndk::ScopedAStatus getExecutionInfo(Timing* timingLaunched, Timing* timingFenced,
+                                        ErrorStatus* errorStatus) override {
+        const auto result = kCallback();
+        if (result.ok()) {
+            const auto& [nnTimingLaunched, nnTimingFenced] = result.value();
+            *timingLaunched = utils::convert(nnTimingLaunched).value();
+            *timingFenced = utils::convert(nnTimingFenced).value();
+            *errorStatus = ErrorStatus::NONE;
+        } else {
+            constexpr auto kNoTiming = Timing{.timeOnDeviceNs = -1, .timeInDriverNs = -1};
+            const auto& [message, code] = result.error();
+            LOG(ERROR) << "getExecutionInfo failed with " << code << ": " << message;
+            const auto aidlStatus = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
+            *timingLaunched = kNoTiming;
+            *timingFenced = kNoTiming;
+            *errorStatus = aidlStatus;
+        }
+        return ndk::ScopedAStatus::ok();
+    }
+
+  private:
+    const nn::ExecuteFencedInfoCallback kCallback;
+};
+
+template <typename Type>
+auto convertInput(const Type& object) -> decltype(nn::convert(std::declval<Type>())) {
+    auto result = nn::convert(object);
+    if (!result.has_value()) {
+        result.error().code = nn::ErrorStatus::INVALID_ARGUMENT;
+    }
+    return result;
+}
+
+nn::GeneralResult<std::vector<nn::SyncFence>> convertSyncFences(
+        const std::vector<ndk::ScopedFileDescriptor>& waitFor) {
+    auto handles = NN_TRY(convertInput(waitFor));
+
+    constexpr auto valid = [](const nn::SharedHandle& handle) {
+        return handle != nullptr && handle->ok();
+    };
+    if (!std::all_of(handles.begin(), handles.end(), valid)) {
+        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid sync fence";
+    }
+
+    std::vector<nn::SyncFence> syncFences;
+    syncFences.reserve(waitFor.size());
+    for (auto& handle : handles) {
+        syncFences.push_back(nn::SyncFence::create(std::move(handle)).value());
+    }
+    return syncFences;
+}
+
+nn::Duration makeDuration(int64_t durationNs) {
+    return nn::Duration(std::chrono::nanoseconds(durationNs));
+}
+
+nn::GeneralResult<nn::OptionalDuration> makeOptionalDuration(int64_t durationNs) {
+    if (durationNs < -1) {
+        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid duration " << durationNs;
+    }
+    return durationNs < 0 ? nn::OptionalDuration{} : makeDuration(durationNs);
+}
+
+nn::GeneralResult<nn::OptionalTimePoint> makeOptionalTimePoint(int64_t durationNs) {
+    if (durationNs < -1) {
+        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid time point " << durationNs;
+    }
+    return durationNs < 0 ? nn::OptionalTimePoint{} : nn::TimePoint(makeDuration(durationNs));
+}
+
+nn::ExecutionResult<ExecutionResult> executeSynchronously(
+        const nn::IPreparedModel& preparedModel, const Request& request, bool measureTiming,
+        int64_t deadlineNs, int64_t loopTimeoutDurationNs, const std::vector<TokenValuePair>& hints,
+        const std::vector<ExtensionNameAndPrefix>& extensionNameToPrefix) {
+    const auto nnRequest = NN_TRY(convertInput(request));
+    const auto nnMeasureTiming = measureTiming ? nn::MeasureTiming::YES : nn::MeasureTiming::NO;
+    const auto nnDeadline = NN_TRY(makeOptionalTimePoint(deadlineNs));
+    const auto nnLoopTimeoutDuration = NN_TRY(makeOptionalDuration(loopTimeoutDurationNs));
+    auto nnHints = NN_TRY(convertInput(hints));
+    auto nnExtensionNameToPrefix = NN_TRY(convertInput(extensionNameToPrefix));
+
+    const auto result =
+            preparedModel.execute(nnRequest, nnMeasureTiming, nnDeadline, nnLoopTimeoutDuration,
+                                  nnHints, nnExtensionNameToPrefix);
+
+    if (!result.ok() && result.error().code == nn::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE) {
+        const auto& [message, code, outputShapes] = result.error();
+        LOG(ERROR) << "executeSynchronously failed with " << code << ": " << message;
+        return ExecutionResult{.outputSufficientSize = false,
+                               .outputShapes = utils::convert(outputShapes).value(),
+                               .timing = {.timeInDriverNs = -1, .timeOnDeviceNs = -1}};
+    }
+
+    const auto& [outputShapes, timing] = NN_TRY(result);
+    return ExecutionResult{.outputSufficientSize = true,
+                           .outputShapes = utils::convert(outputShapes).value(),
+                           .timing = utils::convert(timing).value()};
+}
+
+nn::GeneralResult<FencedExecutionResult> executeFenced(
+        const nn::IPreparedModel& preparedModel, const Request& request,
+        const std::vector<ndk::ScopedFileDescriptor>& waitFor, bool measureTiming,
+        int64_t deadlineNs, int64_t loopTimeoutDurationNs, int64_t durationNs,
+        const std::vector<TokenValuePair>& hints,
+        const std::vector<ExtensionNameAndPrefix>& extensionNameToPrefix) {
+    const auto nnRequest = NN_TRY(convertInput(request));
+    const auto nnWaitFor = NN_TRY(convertSyncFences(waitFor));
+    const auto nnMeasureTiming = measureTiming ? nn::MeasureTiming::YES : nn::MeasureTiming::NO;
+    const auto nnDeadline = NN_TRY(makeOptionalTimePoint(deadlineNs));
+    const auto nnLoopTimeoutDuration = NN_TRY(makeOptionalDuration(loopTimeoutDurationNs));
+    const auto nnDuration = NN_TRY(makeOptionalDuration(durationNs));
+    auto nnHints = NN_TRY(convertInput(hints));
+    auto nnExtensionNameToPrefix = NN_TRY(convertInput(extensionNameToPrefix));
+
+    auto [syncFence, executeFencedInfoCallback] = NN_TRY(preparedModel.executeFenced(
+            nnRequest, nnWaitFor, nnMeasureTiming, nnDeadline, nnLoopTimeoutDuration, nnDuration,
+            nnHints, nnExtensionNameToPrefix));
+
+    ndk::ScopedFileDescriptor fileDescriptor;
+    if (syncFence.hasFd()) {
+        auto uniqueFd = NN_TRY(nn::dupFd(syncFence.getFd()));
+        fileDescriptor = ndk::ScopedFileDescriptor(uniqueFd.release());
+    }
+
+    return FencedExecutionResult{.callback = ndk::SharedRefBase::make<FencedExecutionCallback>(
+                                         std::move(executeFencedInfoCallback)),
+                                 .syncFence = std::move(fileDescriptor)};
+}
+
+nn::GeneralResult<nn::SharedExecution> createReusableExecution(
+        const nn::IPreparedModel& preparedModel, const Request& request, bool measureTiming,
+        int64_t loopTimeoutDurationNs, const std::vector<TokenValuePair>& hints,
+        const std::vector<ExtensionNameAndPrefix>& extensionNameToPrefix) {
+    const auto nnRequest = NN_TRY(convertInput(request));
+    const auto nnMeasureTiming = measureTiming ? nn::MeasureTiming::YES : nn::MeasureTiming::NO;
+    const auto nnLoopTimeoutDuration = NN_TRY(makeOptionalDuration(loopTimeoutDurationNs));
+    auto nnHints = NN_TRY(convertInput(hints));
+    auto nnExtensionNameToPrefix = NN_TRY(convertInput(extensionNameToPrefix));
+
+    return preparedModel.createReusableExecution(nnRequest, nnMeasureTiming, nnLoopTimeoutDuration,
+                                                 nnHints, nnExtensionNameToPrefix);
+}
+
+nn::ExecutionResult<ExecutionResult> executeSynchronously(const nn::IExecution& execution,
+                                                          int64_t deadlineNs) {
+    const auto nnDeadline = NN_TRY(makeOptionalTimePoint(deadlineNs));
+
+    const auto result = execution.compute(nnDeadline);
+
+    if (!result.ok() && result.error().code == nn::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE) {
+        const auto& [message, code, outputShapes] = result.error();
+        LOG(ERROR) << "executeSynchronously failed with " << code << ": " << message;
+        return ExecutionResult{.outputSufficientSize = false,
+                               .outputShapes = utils::convert(outputShapes).value(),
+                               .timing = {.timeInDriverNs = -1, .timeOnDeviceNs = -1}};
+    }
+
+    const auto& [outputShapes, timing] = NN_TRY(result);
+    return ExecutionResult{.outputSufficientSize = true,
+                           .outputShapes = utils::convert(outputShapes).value(),
+                           .timing = utils::convert(timing).value()};
+}
+
+nn::GeneralResult<FencedExecutionResult> executeFenced(
+        const nn::IExecution& execution, const std::vector<ndk::ScopedFileDescriptor>& waitFor,
+        int64_t deadlineNs, int64_t durationNs) {
+    const auto nnWaitFor = NN_TRY(convertSyncFences(waitFor));
+    const auto nnDeadline = NN_TRY(makeOptionalTimePoint(deadlineNs));
+    const auto nnDuration = NN_TRY(makeOptionalDuration(durationNs));
+
+    auto [syncFence, executeFencedInfoCallback] =
+            NN_TRY(execution.computeFenced(nnWaitFor, nnDeadline, nnDuration));
+
+    ndk::ScopedFileDescriptor fileDescriptor;
+    if (syncFence.hasFd()) {
+        auto uniqueFd = NN_TRY(nn::dupFd(syncFence.getFd()));
+        fileDescriptor = ndk::ScopedFileDescriptor(uniqueFd.release());
+    }
+
+    return FencedExecutionResult{.callback = ndk::SharedRefBase::make<FencedExecutionCallback>(
+                                         std::move(executeFencedInfoCallback)),
+                                 .syncFence = std::move(fileDescriptor)};
+}
+
+}  // namespace
+
+PreparedModel::PreparedModel(nn::SharedPreparedModel preparedModel)
+    : kPreparedModel(std::move(preparedModel)) {
+    CHECK(kPreparedModel != nullptr);
+}
+
+ndk::ScopedAStatus PreparedModel::executeSynchronously(const Request& request, bool measureTiming,
+                                                       int64_t deadlineNs,
+                                                       int64_t loopTimeoutDurationNs,
+                                                       ExecutionResult* executionResult) {
+    auto result = adapter::executeSynchronously(*kPreparedModel, request, measureTiming, deadlineNs,
+                                                loopTimeoutDurationNs, {}, {});
+    if (!result.has_value()) {
+        const auto& [message, code, _] = result.error();
+        const auto aidlCode = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
+        return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+                static_cast<int32_t>(aidlCode), message.c_str());
+    }
+    *executionResult = std::move(result).value();
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus PreparedModel::executeFenced(
+        const Request& request, const std::vector<ndk::ScopedFileDescriptor>& waitFor,
+        bool measureTiming, int64_t deadlineNs, int64_t loopTimeoutDurationNs, int64_t durationNs,
+        FencedExecutionResult* executionResult) {
+    auto result = adapter::executeFenced(*kPreparedModel, request, waitFor, measureTiming,
+                                         deadlineNs, loopTimeoutDurationNs, durationNs, {}, {});
+    if (!result.has_value()) {
+        const auto& [message, code] = result.error();
+        const auto aidlCode = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
+        return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+                static_cast<int32_t>(aidlCode), message.c_str());
+    }
+    *executionResult = std::move(result).value();
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus PreparedModel::executeSynchronouslyWithConfig(const Request& request,
+                                                                 const ExecutionConfig& config,
+                                                                 int64_t deadlineNs,
+                                                                 ExecutionResult* executionResult) {
+    auto result = adapter::executeSynchronously(
+            *kPreparedModel, request, config.measureTiming, deadlineNs,
+            config.loopTimeoutDurationNs, config.executionHints, config.extensionNameToPrefix);
+    if (!result.has_value()) {
+        const auto& [message, code, _] = result.error();
+        const auto aidlCode = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
+        return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+                static_cast<int32_t>(aidlCode), message.c_str());
+    }
+    *executionResult = std::move(result).value();
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus PreparedModel::executeFencedWithConfig(
+        const Request& request, const std::vector<ndk::ScopedFileDescriptor>& waitFor,
+        const ExecutionConfig& config, int64_t deadlineNs, int64_t durationNs,
+        FencedExecutionResult* executionResult) {
+    auto result = adapter::executeFenced(*kPreparedModel, request, waitFor, config.measureTiming,
+                                         deadlineNs, config.loopTimeoutDurationNs, durationNs,
+                                         config.executionHints, config.extensionNameToPrefix);
+    if (!result.has_value()) {
+        const auto& [message, code] = result.error();
+        const auto aidlCode = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
+        return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+                static_cast<int32_t>(aidlCode), message.c_str());
+    }
+    *executionResult = std::move(result).value();
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus PreparedModel::configureExecutionBurst(std::shared_ptr<IBurst>* burst) {
+    auto result = kPreparedModel->configureExecutionBurst();
+    if (!result.has_value()) {
+        const auto& [message, code] = result.error();
+        const auto aidlCode = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
+        return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+                static_cast<int32_t>(aidlCode), message.c_str());
+    }
+    *burst = ndk::SharedRefBase::make<Burst>(std::move(result).value());
+    return ndk::ScopedAStatus::ok();
+}
+
+nn::SharedPreparedModel PreparedModel::getUnderlyingPreparedModel() const {
+    return kPreparedModel;
+}
+
+ndk::ScopedAStatus PreparedModel::createReusableExecution(const Request& request,
+                                                          const ExecutionConfig& config,
+                                                          std::shared_ptr<IExecution>* execution) {
+    auto result = adapter::createReusableExecution(
+            *kPreparedModel, request, config.measureTiming, config.loopTimeoutDurationNs,
+            config.executionHints, config.extensionNameToPrefix);
+    if (!result.has_value()) {
+        const auto& [message, code] = result.error();
+        const auto aidlCode = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
+        return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+                static_cast<int32_t>(aidlCode), message.c_str());
+    }
+    *execution = ndk::SharedRefBase::make<Execution>(std::move(result).value());
+    return ndk::ScopedAStatus::ok();
+}
+
+Execution::Execution(nn::SharedExecution execution) : kExecution(std::move(execution)) {
+    CHECK(kExecution != nullptr);
+}
+
+ndk::ScopedAStatus Execution::executeSynchronously(int64_t deadlineNs,
+                                                   ExecutionResult* executionResult) {
+    auto result = adapter::executeSynchronously(*kExecution, deadlineNs);
+    if (!result.has_value()) {
+        const auto& [message, code, _] = result.error();
+        const auto aidlCode = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
+        return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+                static_cast<int32_t>(aidlCode), message.c_str());
+    }
+    *executionResult = std::move(result).value();
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Execution::executeFenced(const std::vector<ndk::ScopedFileDescriptor>& waitFor,
+                                            int64_t deadlineNs, int64_t durationNs,
+                                            FencedExecutionResult* executionResult) {
+    auto result = adapter::executeFenced(*kExecution, waitFor, deadlineNs, durationNs);
+    if (!result.has_value()) {
+        const auto& [message, code] = result.error();
+        const auto aidlCode = utils::convert(code).value_or(ErrorStatus::GENERAL_FAILURE);
+        return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+                static_cast<int32_t>(aidlCode), message.c_str());
+    }
+    *executionResult = std::move(result).value();
+    return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace aidl::android::hardware::neuralnetworks::adapter
diff --git a/neuralnetworks/utils/adapter/hidl/Android.bp b/neuralnetworks/utils/adapter/hidl/Android.bp
new file mode 100644
index 0000000..6875daa
--- /dev/null
+++ b/neuralnetworks/utils/adapter/hidl/Android.bp
@@ -0,0 +1,45 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_library_static {
+    name: "neuralnetworks_utils_hal_adapter",
+    defaults: ["neuralnetworks_utils_defaults"],
+    srcs: ["src/*"],
+    local_include_dirs: ["include/nnapi/hal"],
+    export_include_dirs: ["include"],
+    static_libs: [
+        "android.hardware.neuralnetworks@1.0",
+        "android.hardware.neuralnetworks@1.1",
+        "android.hardware.neuralnetworks@1.2",
+        "android.hardware.neuralnetworks@1.3",
+        "libfmq",
+        "neuralnetworks_types",
+        "neuralnetworks_utils_hal_1_0",
+        "neuralnetworks_utils_hal_1_1",
+        "neuralnetworks_utils_hal_1_2",
+        "neuralnetworks_utils_hal_1_3",
+        "neuralnetworks_utils_hal_common",
+    ],
+}
diff --git a/neuralnetworks/utils/adapter/hidl/include/nnapi/hal/Adapter.h b/neuralnetworks/utils/adapter/hidl/include/nnapi/hal/Adapter.h
new file mode 100644
index 0000000..3bd93e0
--- /dev/null
+++ b/neuralnetworks/utils/adapter/hidl/include/nnapi/hal/Adapter.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_ADAPTER_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_ADAPTER_H
+
+#include <android/hardware/neuralnetworks/1.3/IDevice.h>
+#include <nnapi/IDevice.h>
+#include <nnapi/Types.h>
+#include <functional>
+#include <memory>
+
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
+// lifetimes across processes and for protecting asynchronous calls across HIDL.
+
+namespace android::hardware::neuralnetworks::adapter {
+
+/**
+ * A self-contained unit of work to be executed.
+ */
+using Task = std::function<void()>;
+
+/**
+ * A type-erased executor which executes a task asynchronously.
+ *
+ * This executor is also provided an optional deadline for when the caller expects is the upper
+ * bound for the amount of time to complete the task. If needed, the Executor can retrieve the
+ * Application ID (Android User ID) by calling IPCThreadState::self()->getCallingUid() in
+ * hwbinder/IPCThreadState.h.
+ */
+using Executor = std::function<void(Task, nn::OptionalTimePoint)>;
+
+/**
+ * Adapt an NNAPI canonical interface object to a HIDL NN HAL interface object.
+ *
+ * @param device NNAPI canonical IDevice interface object to be adapted.
+ * @param executor Type-erased executor to handle executing tasks asynchronously.
+ * @return HIDL NN HAL IDevice interface object.
+ */
+sp<V1_3::IDevice> adapt(nn::SharedDevice device, Executor executor);
+
+/**
+ * Adapt an NNAPI canonical interface object to a HIDL NN HAL interface object.
+ *
+ * This function uses a default executor, which will execute tasks from a detached thread.
+ *
+ * @param device NNAPI canonical IDevice interface object to be adapted.
+ * @return HIDL NN HAL IDevice interface object.
+ */
+sp<V1_3::IDevice> adapt(nn::SharedDevice device);
+
+}  // namespace android::hardware::neuralnetworks::adapter
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_ADAPTER_H
diff --git a/neuralnetworks/utils/adapter/include/nnapi/hal/Buffer.h b/neuralnetworks/utils/adapter/hidl/include/nnapi/hal/Buffer.h
similarity index 100%
rename from neuralnetworks/utils/adapter/include/nnapi/hal/Buffer.h
rename to neuralnetworks/utils/adapter/hidl/include/nnapi/hal/Buffer.h
diff --git a/neuralnetworks/utils/adapter/hidl/include/nnapi/hal/Burst.h b/neuralnetworks/utils/adapter/hidl/include/nnapi/hal/Burst.h
new file mode 100644
index 0000000..a3aa706
--- /dev/null
+++ b/neuralnetworks/utils/adapter/hidl/include/nnapi/hal/Burst.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_BURST_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_BURST_H
+
+#include <android-base/thread_annotations.h>
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware/neuralnetworks/1.2/IBurstCallback.h>
+#include <android/hardware/neuralnetworks/1.2/IBurstContext.h>
+#include <android/hardware/neuralnetworks/1.2/IPreparedModel.h>
+#include <android/hardware/neuralnetworks/1.2/types.h>
+#include <fmq/MessageQueue.h>
+#include <hidl/MQDescriptor.h>
+#include <nnapi/IBurst.h>
+#include <nnapi/Result.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/1.0/ProtectCallback.h>
+#include <nnapi/hal/1.2/BurstUtils.h>
+
+#include <atomic>
+#include <chrono>
+#include <memory>
+#include <optional>
+#include <thread>
+#include <tuple>
+#include <vector>
+
+namespace android::hardware::neuralnetworks::adapter {
+
+/**
+ * The Burst class is responsible for waiting for and deserializing a request object from a FMQ,
+ * performing the inference, and serializing the result back across another FMQ.
+ */
+class Burst : public V1_2::IBurstContext {
+    struct PrivateConstructorTag {};
+
+  public:
+    /**
+     * Class to cache the memory objects for a burst object.
+     *
+     * This class is thread-safe.
+     */
+    class MemoryCache {
+      public:
+        // Precondition: burstExecutor != nullptr
+        // Precondition: burstCallback != nullptr
+        MemoryCache(nn::SharedBurst burstExecutor, sp<V1_2::IBurstCallback> burstCallback);
+
+        /**
+         * Get the cached memory objects corresponding to provided slot identifiers.
+         *
+         * If the slot entry is not present in the cache, this class will use V1_2::IBurstCallback
+         * to retrieve those entries that are not present in the cache, then cache them.
+         *
+         * @param slots Identifiers of memory objects to be retrieved.
+         * @return A vector where each element is the memory object and a ref-counted cache "hold"
+         *     object to preserve the cache entry of the IBurst object as long as the "hold" object
+         *     is alive, otherwise GeneralError. Each element of the vector corresponds to the
+         *     element of slot.
+         */
+        nn::GeneralResult<std::vector<std::pair<nn::SharedMemory, nn::IBurst::OptionalCacheHold>>>
+        getCacheEntries(const std::vector<int32_t>& slots);
+
+        /**
+         * Remove an entry from the cache.
+         *
+         * @param slot Identifier of the memory object to be removed from the cache.
+         */
+        void removeCacheEntry(int32_t slot);
+
+      private:
+        nn::GeneralResult<void> ensureCacheEntriesArePresentLocked(
+                const std::vector<int32_t>& slots) REQUIRES(mMutex);
+        nn::GeneralResult<std::pair<nn::SharedMemory, nn::IBurst::OptionalCacheHold>>
+        getCacheEntryLocked(int32_t slot) REQUIRES(mMutex);
+        void addCacheEntryLocked(int32_t slot, nn::SharedMemory memory) REQUIRES(mMutex);
+
+        std::mutex mMutex;
+        std::map<int32_t, std::pair<nn::SharedMemory, nn::IBurst::OptionalCacheHold>> mCache
+                GUARDED_BY(mMutex);
+        nn::SharedBurst kBurstExecutor;
+        const sp<V1_2::IBurstCallback> kBurstCallback;
+    };
+
+    /**
+     * Create automated context to manage FMQ-based executions.
+     *
+     * This function is intended to be used by a service to automatically:
+     * 1) Receive data from a provided FMQ
+     * 2) Execute a model with the given information
+     * 3) Send the result to the created FMQ
+     *
+     * @param callback Callback used to retrieve memories corresponding to unrecognized slots.
+     * @param requestChannel Input FMQ channel through which the client passes the request to the
+     *     service.
+     * @param resultChannel Output FMQ channel from which the client can retrieve the result of the
+     *     execution.
+     * @param burstExecutor Object which maintains a local cache of the memory pools and executes
+     *     using the cached memory pools.
+     * @param pollingTimeWindow How much time (in microseconds) the Burst is allowed to poll the FMQ
+     *     before waiting on the blocking futex. Polling may result in lower latencies at the
+     *     potential cost of more power usage.
+     * @return V1_2::IBurstContext Handle to the burst context.
+     */
+    static nn::GeneralResult<sp<Burst>> create(
+            const sp<V1_2::IBurstCallback>& callback,
+            const MQDescriptorSync<V1_2::FmqRequestDatum>& requestChannel,
+            const MQDescriptorSync<V1_2::FmqResultDatum>& resultChannel,
+            nn::SharedBurst burstExecutor,
+            std::chrono::microseconds pollingTimeWindow = std::chrono::microseconds{0});
+
+    Burst(PrivateConstructorTag tag, const sp<V1_2::IBurstCallback>& callback,
+          std::unique_ptr<V1_2::utils::RequestChannelReceiver> requestChannel,
+          std::unique_ptr<V1_2::utils::ResultChannelSender> resultChannel,
+          nn::SharedBurst burstExecutor);
+    ~Burst();
+
+    // Used by the NN runtime to preemptively remove any stored memory. See
+    // V1_2::IBurstContext::freeMemory for more information.
+    Return<void> freeMemory(int32_t slot) override;
+
+  private:
+    // Work loop that will continue processing execution requests until the Burst object is freed.
+    void task();
+
+    nn::ExecutionResult<std::pair<hidl_vec<V1_2::OutputShape>, V1_2::Timing>> execute(
+            const V1_0::Request& requestWithoutPools, const std::vector<int32_t>& slotsOfPools,
+            V1_2::MeasureTiming measure);
+
+    std::thread mWorker;
+    std::atomic<bool> mTeardown{false};
+    const sp<V1_2::IBurstCallback> mCallback;
+    const std::unique_ptr<V1_2::utils::RequestChannelReceiver> mRequestChannelReceiver;
+    const std::unique_ptr<V1_2::utils::ResultChannelSender> mResultChannelSender;
+    const nn::SharedBurst mBurstExecutor;
+    MemoryCache mMemoryCache;
+};
+
+}  // namespace android::hardware::neuralnetworks::adapter
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_BURST_H
diff --git a/neuralnetworks/utils/adapter/include/nnapi/hal/Device.h b/neuralnetworks/utils/adapter/hidl/include/nnapi/hal/Device.h
similarity index 100%
rename from neuralnetworks/utils/adapter/include/nnapi/hal/Device.h
rename to neuralnetworks/utils/adapter/hidl/include/nnapi/hal/Device.h
diff --git a/neuralnetworks/utils/adapter/hidl/include/nnapi/hal/PreparedModel.h b/neuralnetworks/utils/adapter/hidl/include/nnapi/hal/PreparedModel.h
new file mode 100644
index 0000000..01cd4bc
--- /dev/null
+++ b/neuralnetworks/utils/adapter/hidl/include/nnapi/hal/PreparedModel.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_PREPARED_MODEL_H
+#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_PREPARED_MODEL_H
+
+#include "nnapi/hal/Adapter.h"
+
+#include <android/hardware/neuralnetworks/1.0/IExecutionCallback.h>
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware/neuralnetworks/1.2/IBurstCallback.h>
+#include <android/hardware/neuralnetworks/1.2/IExecutionCallback.h>
+#include <android/hardware/neuralnetworks/1.2/types.h>
+#include <android/hardware/neuralnetworks/1.3/IExecutionCallback.h>
+#include <android/hardware/neuralnetworks/1.3/IPreparedModel.h>
+#include <android/hardware/neuralnetworks/1.3/types.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Types.h>
+#include <memory>
+
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
+// lifetimes across processes and for protecting asynchronous calls across HIDL.
+
+namespace android::hardware::neuralnetworks::adapter {
+
+// Class that adapts nn::IPreparedModel to V1_3::IPreparedModel.
+class PreparedModel final : public V1_3::IPreparedModel {
+  public:
+    explicit PreparedModel(nn::SharedPreparedModel preparedModel);
+
+    Return<V1_0::ErrorStatus> execute(const V1_0::Request& request,
+                                      const sp<V1_0::IExecutionCallback>& callback) override;
+    Return<V1_0::ErrorStatus> execute_1_2(const V1_0::Request& request, V1_2::MeasureTiming measure,
+                                          const sp<V1_2::IExecutionCallback>& callback) override;
+    Return<V1_3::ErrorStatus> execute_1_3(const V1_3::Request& request, V1_2::MeasureTiming measure,
+                                          const V1_3::OptionalTimePoint& deadline,
+                                          const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
+                                          const sp<V1_3::IExecutionCallback>& callback) override;
+    Return<void> executeSynchronously(const V1_0::Request& request, V1_2::MeasureTiming measure,
+                                      executeSynchronously_cb cb) override;
+    Return<void> executeSynchronously_1_3(const V1_3::Request& request, V1_2::MeasureTiming measure,
+                                          const V1_3::OptionalTimePoint& deadline,
+                                          const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
+                                          executeSynchronously_1_3_cb cb) override;
+    Return<void> configureExecutionBurst(
+            const sp<V1_2::IBurstCallback>& callback,
+            const MQDescriptorSync<V1_2::FmqRequestDatum>& requestChannel,
+            const MQDescriptorSync<V1_2::FmqResultDatum>& resultChannel,
+            configureExecutionBurst_cb cb) override;
+    Return<void> executeFenced(const V1_3::Request& request, const hidl_vec<hidl_handle>& waitFor,
+                               V1_2::MeasureTiming measure, const V1_3::OptionalTimePoint& deadline,
+                               const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
+                               const V1_3::OptionalTimeoutDuration& duration,
+                               executeFenced_cb callback) override;
+
+    nn::SharedPreparedModel getUnderlyingPreparedModel() const;
+
+  private:
+    const nn::SharedPreparedModel kPreparedModel;
+};
+
+}  // namespace android::hardware::neuralnetworks::adapter
+
+#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_PREPARED_MODEL_H
diff --git a/neuralnetworks/utils/adapter/hidl/src/Adapter.cpp b/neuralnetworks/utils/adapter/hidl/src/Adapter.cpp
new file mode 100644
index 0000000..782e815
--- /dev/null
+++ b/neuralnetworks/utils/adapter/hidl/src/Adapter.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "Adapter.h"
+
+#include "Device.h"
+
+#include <android/hardware/neuralnetworks/1.3/IDevice.h>
+#include <nnapi/IDevice.h>
+#include <nnapi/Types.h>
+
+#include <functional>
+#include <memory>
+#include <thread>
+
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
+// lifetimes across processes and for protecting asynchronous calls across HIDL.
+
+namespace android::hardware::neuralnetworks::adapter {
+
+sp<V1_3::IDevice> adapt(nn::SharedDevice device, Executor executor) {
+    return sp<Device>::make(std::move(device), std::move(executor));
+}
+
+sp<V1_3::IDevice> adapt(nn::SharedDevice device) {
+    Executor defaultExecutor = [](Task task, nn::OptionalTimePoint /*deadline*/) {
+        std::thread(std::move(task)).detach();
+    };
+    return adapt(std::move(device), std::move(defaultExecutor));
+}
+
+}  // namespace android::hardware::neuralnetworks::adapter
diff --git a/neuralnetworks/utils/adapter/src/Buffer.cpp b/neuralnetworks/utils/adapter/hidl/src/Buffer.cpp
similarity index 100%
rename from neuralnetworks/utils/adapter/src/Buffer.cpp
rename to neuralnetworks/utils/adapter/hidl/src/Buffer.cpp
diff --git a/neuralnetworks/utils/adapter/hidl/src/Burst.cpp b/neuralnetworks/utils/adapter/hidl/src/Burst.cpp
new file mode 100644
index 0000000..e3b165b
--- /dev/null
+++ b/neuralnetworks/utils/adapter/hidl/src/Burst.cpp
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Burst.h"
+
+#include <android-base/logging.h>
+#include <nnapi/IBurst.h>
+#include <nnapi/Result.h>
+#include <nnapi/TypeUtils.h>
+#include <nnapi/Types.h>
+#include <nnapi/Validation.h>
+#include <nnapi/hal/1.0/Conversions.h>
+#include <nnapi/hal/1.0/HandleError.h>
+#include <nnapi/hal/1.0/ProtectCallback.h>
+#include <nnapi/hal/1.2/BurstUtils.h>
+#include <nnapi/hal/1.2/Conversions.h>
+#include <nnapi/hal/TransferValue.h>
+
+#include <algorithm>
+#include <cstring>
+#include <limits>
+#include <map>
+#include <memory>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+#include "Tracing.h"
+
+namespace android::hardware::neuralnetworks::adapter {
+namespace {
+
+constexpr V1_2::Timing kTiming = {std::numeric_limits<uint64_t>::max(),
+                                  std::numeric_limits<uint64_t>::max()};
+
+nn::GeneralResult<std::vector<nn::SharedMemory>> getMemoriesCallback(
+        V1_0::ErrorStatus status, const hidl_vec<hidl_memory>& memories) {
+    HANDLE_STATUS_HIDL(status) << "getting burst memories failed with " << toString(status);
+    std::vector<nn::SharedMemory> canonicalMemories;
+    canonicalMemories.reserve(memories.size());
+    for (const auto& memory : memories) {
+        canonicalMemories.push_back(NN_TRY(nn::convert(memory)));
+    }
+    return canonicalMemories;
+}
+
+}  // anonymous namespace
+
+Burst::MemoryCache::MemoryCache(nn::SharedBurst burstExecutor,
+                                sp<V1_2::IBurstCallback> burstCallback)
+    : kBurstExecutor(std::move(burstExecutor)), kBurstCallback(std::move(burstCallback)) {
+    CHECK(kBurstExecutor != nullptr);
+    CHECK(kBurstCallback != nullptr);
+}
+
+nn::GeneralResult<std::vector<std::pair<nn::SharedMemory, nn::IBurst::OptionalCacheHold>>>
+Burst::MemoryCache::getCacheEntries(const std::vector<int32_t>& slots) {
+    std::lock_guard guard(mMutex);
+    NN_TRY(ensureCacheEntriesArePresentLocked(slots));
+
+    std::vector<std::pair<nn::SharedMemory, nn::IBurst::OptionalCacheHold>> results;
+    results.reserve(slots.size());
+    for (int32_t slot : slots) {
+        results.push_back(NN_TRY(getCacheEntryLocked(slot)));
+    }
+
+    return results;
+}
+
+nn::GeneralResult<void> Burst::MemoryCache::ensureCacheEntriesArePresentLocked(
+        const std::vector<int32_t>& slots) {
+    const auto slotIsKnown = [this](int32_t slot)
+                                     REQUIRES(mMutex) { return mCache.count(slot) > 0; };
+
+    // find unique unknown slots
+    std::vector<int32_t> unknownSlots = slots;
+    std::sort(unknownSlots.begin(), unknownSlots.end());
+    auto unknownSlotsEnd = std::unique(unknownSlots.begin(), unknownSlots.end());
+    unknownSlotsEnd = std::remove_if(unknownSlots.begin(), unknownSlotsEnd, slotIsKnown);
+    unknownSlots.erase(unknownSlotsEnd, unknownSlots.end());
+
+    // quick-exit if all slots are known
+    if (unknownSlots.empty()) {
+        return {};
+    }
+
+    auto cb = neuralnetworks::utils::CallbackValue(getMemoriesCallback);
+
+    const auto ret = kBurstCallback->getMemories(unknownSlots, cb);
+    HANDLE_TRANSPORT_FAILURE(ret);
+
+    auto returnedMemories = NN_TRY(cb.take());
+
+    if (returnedMemories.size() != unknownSlots.size()) {
+        return NN_ERROR() << "Burst::MemoryCache::ensureCacheEntriesArePresentLocked: Error "
+                             "retrieving memories -- count mismatch between requested memories ("
+                          << unknownSlots.size() << ") and returned memories ("
+                          << returnedMemories.size() << ")";
+    }
+
+    // add memories to unknown slots
+    for (size_t i = 0; i < unknownSlots.size(); ++i) {
+        addCacheEntryLocked(unknownSlots[i], std::move(returnedMemories[i]));
+    }
+
+    return {};
+}
+
+nn::GeneralResult<std::pair<nn::SharedMemory, nn::IBurst::OptionalCacheHold>>
+Burst::MemoryCache::getCacheEntryLocked(int32_t slot) {
+    if (const auto iter = mCache.find(slot); iter != mCache.end()) {
+        return iter->second;
+    }
+    return NN_ERROR() << "Burst::MemoryCache::getCacheEntryLocked failed because slot " << slot
+                      << " is not present in the cache";
+}
+
+void Burst::MemoryCache::addCacheEntryLocked(int32_t slot, nn::SharedMemory memory) {
+    auto hold = kBurstExecutor->cacheMemory(memory);
+    mCache.emplace(slot, std::make_pair(std::move(memory), std::move(hold)));
+}
+
+void Burst::MemoryCache::removeCacheEntry(int32_t slot) {
+    std::lock_guard guard(mMutex);
+    mCache.erase(slot);
+}
+
+// Burst methods
+
+nn::GeneralResult<sp<Burst>> Burst::create(
+        const sp<V1_2::IBurstCallback>& callback,
+        const MQDescriptorSync<V1_2::FmqRequestDatum>& requestChannel,
+        const MQDescriptorSync<V1_2::FmqResultDatum>& resultChannel, nn::SharedBurst burstExecutor,
+        std::chrono::microseconds pollingTimeWindow) {
+    // check inputs
+    if (callback == nullptr || burstExecutor == nullptr) {
+        return NN_ERROR() << "Burst::create passed a nullptr";
+    }
+
+    // create FMQ objects
+    auto requestChannelReceiver =
+            NN_TRY(V1_2::utils::RequestChannelReceiver::create(requestChannel, pollingTimeWindow));
+    auto resultChannelSender = NN_TRY(V1_2::utils::ResultChannelSender::create(resultChannel));
+
+    // check FMQ objects
+    CHECK(requestChannelReceiver != nullptr);
+    CHECK(resultChannelSender != nullptr);
+
+    // make and return context
+    return sp<Burst>::make(PrivateConstructorTag{}, callback, std::move(requestChannelReceiver),
+                           std::move(resultChannelSender), std::move(burstExecutor));
+}
+
+Burst::Burst(PrivateConstructorTag /*tag*/, const sp<V1_2::IBurstCallback>& callback,
+             std::unique_ptr<V1_2::utils::RequestChannelReceiver> requestChannel,
+             std::unique_ptr<V1_2::utils::ResultChannelSender> resultChannel,
+             nn::SharedBurst burstExecutor)
+    : mCallback(callback),
+      mRequestChannelReceiver(std::move(requestChannel)),
+      mResultChannelSender(std::move(resultChannel)),
+      mBurstExecutor(std::move(burstExecutor)),
+      mMemoryCache(mBurstExecutor, mCallback) {
+    // TODO: highly document the threading behavior of this class
+    mWorker = std::thread([this] { task(); });
+}
+
+Burst::~Burst() {
+    // set teardown flag
+    mTeardown = true;
+    mRequestChannelReceiver->invalidate();
+
+    // wait for task thread to end
+    mWorker.join();
+}
+
+Return<void> Burst::freeMemory(int32_t slot) {
+    mMemoryCache.removeCacheEntry(slot);
+    return Void();
+}
+
+void Burst::task() {
+    // loop until the burst object is being destroyed
+    while (!mTeardown) {
+        // receive request
+        auto arguments = mRequestChannelReceiver->getBlocking();
+
+        // if the request packet was not properly received, return a generic error and skip the
+        // execution
+        //
+        // if the burst is being torn down, skip the execution so the "task" function can end
+        if (!arguments.has_value()) {
+            if (!mTeardown) {
+                mResultChannelSender->send(V1_0::ErrorStatus::GENERAL_FAILURE, {}, kTiming);
+            }
+            continue;
+        }
+
+        // unpack the arguments; types are Request, std::vector<int32_t>, and V1_2::MeasureTiming,
+        // respectively
+        const auto [requestWithoutPools, slotsOfPools, measure] = std::move(arguments).value();
+
+        auto result = execute(requestWithoutPools, slotsOfPools, measure);
+
+        // return result
+        if (result.has_value()) {
+            const auto& [outputShapes, timing] = result.value();
+            mResultChannelSender->send(V1_0::ErrorStatus::NONE, outputShapes, timing);
+        } else {
+            const auto& [message, code, outputShapes] = result.error();
+            LOG(ERROR) << "IBurst::execute failed with " << code << ": " << message;
+            mResultChannelSender->send(V1_2::utils::convert(code).value(),
+                                       V1_2::utils::convert(outputShapes).value(), kTiming);
+        }
+    }
+}
+
+nn::ExecutionResult<std::pair<hidl_vec<V1_2::OutputShape>, V1_2::Timing>> Burst::execute(
+        const V1_0::Request& requestWithoutPools, const std::vector<int32_t>& slotsOfPools,
+        V1_2::MeasureTiming measure) {
+    NNTRACE_FULL(NNTRACE_LAYER_IPC, NNTRACE_PHASE_EXECUTION,
+                 "Burst getting memory, executing, and returning results");
+
+    // ensure executor with cache has required memory
+    const auto cacheEntries = NN_TRY(mMemoryCache.getCacheEntries(slotsOfPools));
+
+    // convert request, populating its pools
+    // This code performs an unvalidated convert because the request object without its pools is
+    // invalid because it is incomplete. Instead, the validation is performed after the memory pools
+    // have been added to the request.
+    auto canonicalRequest = NN_TRY(nn::unvalidatedConvert(requestWithoutPools));
+    CHECK(canonicalRequest.pools.empty());
+    std::transform(cacheEntries.begin(), cacheEntries.end(),
+                   std::back_inserter(canonicalRequest.pools),
+                   [](const auto& cacheEntry) { return cacheEntry.first; });
+    NN_TRY(validate(canonicalRequest));
+
+    nn::MeasureTiming canonicalMeasure = NN_TRY(nn::convert(measure));
+
+    const auto [outputShapes, timing] =
+            NN_TRY(mBurstExecutor->execute(canonicalRequest, canonicalMeasure, {}, {}, {}, {}));
+
+    return std::make_pair(NN_TRY(V1_2::utils::convert(outputShapes)),
+                          NN_TRY(V1_2::utils::convert(timing)));
+}
+
+}  // namespace android::hardware::neuralnetworks::adapter
diff --git a/neuralnetworks/utils/adapter/hidl/src/Device.cpp b/neuralnetworks/utils/adapter/hidl/src/Device.cpp
new file mode 100644
index 0000000..305a1b4
--- /dev/null
+++ b/neuralnetworks/utils/adapter/hidl/src/Device.cpp
@@ -0,0 +1,546 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "Device.h"
+
+#include "Buffer.h"
+#include "PreparedModel.h"
+
+#include <android-base/logging.h>
+#include <android/hardware/neuralnetworks/1.0/IPreparedModelCallback.h>
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware/neuralnetworks/1.1/types.h>
+#include <android/hardware/neuralnetworks/1.2/IPreparedModelCallback.h>
+#include <android/hardware/neuralnetworks/1.2/types.h>
+#include <android/hardware/neuralnetworks/1.3/IDevice.h>
+#include <android/hardware/neuralnetworks/1.3/IPreparedModelCallback.h>
+#include <android/hardware/neuralnetworks/1.3/types.h>
+#include <nnapi/IBuffer.h>
+#include <nnapi/IDevice.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/Result.h>
+#include <nnapi/TypeUtils.h>
+#include <nnapi/Types.h>
+#include <nnapi/hal/1.0/Conversions.h>
+#include <nnapi/hal/1.0/Utils.h>
+#include <nnapi/hal/1.1/Conversions.h>
+#include <nnapi/hal/1.1/Utils.h>
+#include <nnapi/hal/1.2/Conversions.h>
+#include <nnapi/hal/1.2/Utils.h>
+#include <nnapi/hal/1.3/Conversions.h>
+#include <nnapi/hal/1.3/Utils.h>
+
+#include <memory>
+
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
+// lifetimes across processes and for protecting asynchronous calls across HIDL.
+
+namespace android::hardware::neuralnetworks::adapter {
+namespace {
+
+template <typename Type>
+auto convertInput(const Type& object) -> decltype(nn::convert(std::declval<Type>())) {
+    auto result = nn::convert(object);
+    if (!result.has_value()) {
+        result.error().code = nn::ErrorStatus::INVALID_ARGUMENT;
+    }
+    return result;
+}
+
+using PrepareModelResult = nn::GeneralResult<nn::SharedPreparedModel>;
+
+sp<PreparedModel> adaptPreparedModel(nn::SharedPreparedModel preparedModel) {
+    if (preparedModel == nullptr) {
+        return nullptr;
+    }
+    return sp<PreparedModel>::make(std::move(preparedModel));
+}
+
+void notify(V1_0::IPreparedModelCallback* callback, nn::ErrorStatus status,
+            const sp<PreparedModel>& hidlPreparedModel) {
+    if (callback != nullptr) {
+        const auto hidlStatus = V1_0::utils::convert(status).value();
+        const auto ret = callback->notify(hidlStatus, hidlPreparedModel);
+        if (!ret.isOk()) {
+            LOG(ERROR) << "V1_0::IPreparedModelCallback::notify failed with " << ret.description();
+        }
+    }
+}
+
+void notify(V1_2::IPreparedModelCallback* callback, nn::ErrorStatus status,
+            const sp<PreparedModel>& hidlPreparedModel) {
+    if (callback != nullptr) {
+        const auto hidlStatus = V1_2::utils::convert(status).value();
+        const auto ret = callback->notify_1_2(hidlStatus, hidlPreparedModel);
+        if (!ret.isOk()) {
+            LOG(ERROR) << "V1_2::IPreparedModelCallback::notify_1_2 failed with "
+                       << ret.description();
+        }
+    }
+}
+
+void notify(V1_3::IPreparedModelCallback* callback, nn::ErrorStatus status,
+            const sp<PreparedModel>& hidlPreparedModel) {
+    if (callback != nullptr) {
+        const auto hidlStatus = V1_3::utils::convert(status).value();
+        const auto ret = callback->notify_1_3(hidlStatus, hidlPreparedModel);
+        if (!ret.isOk()) {
+            LOG(ERROR) << "V1_3::IPreparedModelCallback::notify_1_3 failed with "
+                       << ret.description();
+        }
+    }
+}
+
+template <typename CallbackType>
+void notify(CallbackType* callback, PrepareModelResult result) {
+    if (!result.has_value()) {
+        const auto [message, status] = std::move(result).error();
+        LOG(ERROR) << message;
+        notify(callback, status, nullptr);
+    } else {
+        auto preparedModel = std::move(result).value();
+        auto hidlPreparedModel = adaptPreparedModel(std::move(preparedModel));
+        notify(callback, nn::ErrorStatus::NONE, std::move(hidlPreparedModel));
+    }
+}
+
+template <typename ModelType>
+nn::GeneralResult<hidl_vec<bool>> getSupportedOperations(const nn::SharedDevice& device,
+                                                         const ModelType& model) {
+    const auto nnModel = NN_TRY(convertInput(model));
+    return NN_TRY(device->getSupportedOperations(nnModel));
+}
+
+nn::GeneralResult<void> prepareModel(const nn::SharedDevice& device, const Executor& executor,
+                                     const V1_0::Model& model,
+                                     const sp<V1_0::IPreparedModelCallback>& callback) {
+    if (callback.get() == nullptr) {
+        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
+    }
+
+    auto nnModel = NN_TRY(convertInput(model));
+
+    Task task = [device, nnModel = std::move(nnModel), callback] {
+        auto result = device->prepareModel(nnModel, nn::ExecutionPreference::DEFAULT,
+                                           nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
+        notify(callback.get(), std::move(result));
+    };
+    executor(std::move(task), {});
+
+    return {};
+}
+
+nn::GeneralResult<void> prepareModel_1_1(const nn::SharedDevice& device, const Executor& executor,
+                                         const V1_1::Model& model,
+                                         V1_1::ExecutionPreference preference,
+                                         const sp<V1_0::IPreparedModelCallback>& callback) {
+    if (callback.get() == nullptr) {
+        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
+    }
+
+    auto nnModel = NN_TRY(convertInput(model));
+    const auto nnPreference = NN_TRY(convertInput(preference));
+
+    Task task = [device, nnModel = std::move(nnModel), nnPreference, callback] {
+        auto result = device->prepareModel(nnModel, nnPreference, nn::Priority::DEFAULT, {}, {}, {},
+                                           {}, {}, {});
+        notify(callback.get(), std::move(result));
+    };
+    executor(std::move(task), {});
+
+    return {};
+}
+
+nn::GeneralResult<void> prepareModel_1_2(const nn::SharedDevice& device, const Executor& executor,
+                                         const V1_2::Model& model,
+                                         V1_1::ExecutionPreference preference,
+                                         const hidl_vec<hidl_handle>& modelCache,
+                                         const hidl_vec<hidl_handle>& dataCache,
+                                         const CacheToken& token,
+                                         const sp<V1_2::IPreparedModelCallback>& callback) {
+    if (callback.get() == nullptr) {
+        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
+    }
+
+    auto nnModel = NN_TRY(convertInput(model));
+    const auto nnPreference = NN_TRY(convertInput(preference));
+    auto nnModelCache = NN_TRY(convertInput(modelCache));
+    auto nnDataCache = NN_TRY(convertInput(dataCache));
+    const auto nnToken = nn::CacheToken(token);
+
+    Task task = [device, nnModel = std::move(nnModel), nnPreference,
+                 nnModelCache = std::move(nnModelCache), nnDataCache = std::move(nnDataCache),
+                 nnToken, callback] {
+        auto result = device->prepareModel(nnModel, nnPreference, nn::Priority::DEFAULT, {},
+                                           nnModelCache, nnDataCache, nnToken, {}, {});
+        notify(callback.get(), std::move(result));
+    };
+    executor(std::move(task), {});
+
+    return {};
+}
+
+nn::GeneralResult<void> prepareModel_1_3(
+        const nn::SharedDevice& device, const Executor& executor, const V1_3::Model& model,
+        V1_1::ExecutionPreference preference, V1_3::Priority priority,
+        const V1_3::OptionalTimePoint& deadline, const hidl_vec<hidl_handle>& modelCache,
+        const hidl_vec<hidl_handle>& dataCache, const CacheToken& token,
+        const sp<V1_3::IPreparedModelCallback>& callback) {
+    if (callback.get() == nullptr) {
+        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
+    }
+
+    auto nnModel = NN_TRY(convertInput(model));
+    const auto nnPreference = NN_TRY(convertInput(preference));
+    const auto nnPriority = NN_TRY(convertInput(priority));
+    const auto nnDeadline = NN_TRY(convertInput(deadline));
+    auto nnModelCache = NN_TRY(convertInput(modelCache));
+    auto nnDataCache = NN_TRY(convertInput(dataCache));
+    const auto nnToken = nn::CacheToken(token);
+
+    Task task = [device, nnModel = std::move(nnModel), nnPreference, nnPriority, nnDeadline,
+                 nnModelCache = std::move(nnModelCache), nnDataCache = std::move(nnDataCache),
+                 nnToken, callback] {
+        auto result = device->prepareModel(nnModel, nnPreference, nnPriority, nnDeadline,
+                                           nnModelCache, nnDataCache, nnToken, {}, {});
+        notify(callback.get(), std::move(result));
+    };
+    executor(std::move(task), nnDeadline);
+
+    return {};
+}
+
+nn::GeneralResult<void> prepareModelFromCache(const nn::SharedDevice& device,
+                                              const Executor& executor,
+                                              const hidl_vec<hidl_handle>& modelCache,
+                                              const hidl_vec<hidl_handle>& dataCache,
+                                              const CacheToken& token,
+                                              const sp<V1_2::IPreparedModelCallback>& callback) {
+    if (callback.get() == nullptr) {
+        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
+    }
+
+    auto nnModelCache = NN_TRY(convertInput(modelCache));
+    auto nnDataCache = NN_TRY(convertInput(dataCache));
+    const auto nnToken = nn::CacheToken(token);
+
+    Task task = [device, nnModelCache = std::move(nnModelCache),
+                 nnDataCache = std::move(nnDataCache), nnToken, callback] {
+        auto result = device->prepareModelFromCache({}, nnModelCache, nnDataCache, nnToken);
+        notify(callback.get(), std::move(result));
+    };
+    executor(std::move(task), {});
+
+    return {};
+}
+
+nn::GeneralResult<void> prepareModelFromCache_1_3(
+        const nn::SharedDevice& device, const Executor& executor,
+        const V1_3::OptionalTimePoint& deadline, const hidl_vec<hidl_handle>& modelCache,
+        const hidl_vec<hidl_handle>& dataCache, const CacheToken& token,
+        const sp<V1_3::IPreparedModelCallback>& callback) {
+    if (callback.get() == nullptr) {
+        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
+    }
+
+    const auto nnDeadline = NN_TRY(convertInput(deadline));
+    auto nnModelCache = NN_TRY(convertInput(modelCache));
+    auto nnDataCache = NN_TRY(convertInput(dataCache));
+    const auto nnToken = nn::CacheToken(token);
+
+    auto task = [device, nnDeadline, nnModelCache = std::move(nnModelCache),
+                 nnDataCache = std::move(nnDataCache), nnToken, callback] {
+        auto result = device->prepareModelFromCache(nnDeadline, nnModelCache, nnDataCache, nnToken);
+        notify(callback.get(), std::move(result));
+    };
+    executor(std::move(task), nnDeadline);
+
+    return {};
+}
+
+nn::GeneralResult<nn::SharedPreparedModel> downcast(const sp<V1_3::IPreparedModel>& preparedModel) {
+    if (preparedModel == nullptr) {
+        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "preparedModel is nullptr";
+    }
+    if (preparedModel->isRemote()) {
+        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Cannot convert remote models";
+    }
+
+    // This static_cast is safe because adapter::PreparedModel is the only class that implements
+    // the IPreparedModel interface in the adapter service code.
+    const auto* casted = static_cast<const PreparedModel*>(preparedModel.get());
+    return casted->getUnderlyingPreparedModel();
+}
+
+nn::GeneralResult<std::vector<nn::SharedPreparedModel>> downcastAll(
+        const hidl_vec<sp<V1_3::IPreparedModel>>& preparedModels) {
+    std::vector<nn::SharedPreparedModel> canonical;
+    canonical.reserve(preparedModels.size());
+    for (const auto& preparedModel : preparedModels) {
+        canonical.push_back(NN_TRY(downcast(preparedModel)));
+    }
+    return canonical;
+}
+
+nn::GeneralResult<std::pair<sp<V1_3::IBuffer>, uint32_t>> allocate(
+        const nn::SharedDevice& device, const V1_3::BufferDesc& desc,
+        const hidl_vec<sp<V1_3::IPreparedModel>>& preparedModels,
+        const hidl_vec<V1_3::BufferRole>& inputRoles,
+        const hidl_vec<V1_3::BufferRole>& outputRoles) {
+    auto nnDesc = NN_TRY(convertInput(desc));
+    auto nnPreparedModels = NN_TRY(downcastAll(preparedModels));
+    auto nnInputRoles = NN_TRY(convertInput(inputRoles));
+    auto nnOutputRoles = NN_TRY(convertInput(outputRoles));
+
+    auto buffer = NN_TRY(device->allocate(nnDesc, nnPreparedModels, nnInputRoles, nnOutputRoles));
+
+    const nn::Request::MemoryDomainToken token = buffer->getToken();
+    auto hidlBuffer = sp<Buffer>::make(std::move(buffer));
+    return std::make_pair(std::move(hidlBuffer), static_cast<uint32_t>(token));
+}
+
+}  // namespace
+
+Device::Device(nn::SharedDevice device, Executor executor)
+    : kDevice(std::move(device)), kExecutor(std::move(executor)) {
+    CHECK(kDevice != nullptr);
+    CHECK(kExecutor != nullptr);
+}
+
+Return<void> Device::getCapabilities(getCapabilities_cb cb) {
+    const auto capabilities = V1_0::utils::convert(kDevice->getCapabilities()).value();
+    cb(V1_0::ErrorStatus::NONE, capabilities);
+    return Void();
+}
+
+Return<void> Device::getCapabilities_1_1(getCapabilities_1_1_cb cb) {
+    const auto capabilities = V1_1::utils::convert(kDevice->getCapabilities()).value();
+    cb(V1_0::ErrorStatus::NONE, capabilities);
+    return Void();
+}
+
+Return<void> Device::getCapabilities_1_2(getCapabilities_1_2_cb cb) {
+    const auto capabilities = V1_2::utils::convert(kDevice->getCapabilities()).value();
+    cb(V1_0::ErrorStatus::NONE, capabilities);
+    return Void();
+}
+
+Return<void> Device::getCapabilities_1_3(getCapabilities_1_3_cb cb) {
+    const auto capabilities = V1_3::utils::convert(kDevice->getCapabilities()).value();
+    cb(V1_3::ErrorStatus::NONE, capabilities);
+    return Void();
+}
+
+Return<void> Device::getVersionString(getVersionString_cb cb) {
+    cb(V1_0::ErrorStatus::NONE, kDevice->getVersionString());
+    return Void();
+}
+
+Return<void> Device::getType(getType_cb cb) {
+    const auto maybeDeviceType = V1_2::utils::convert(kDevice->getType());
+    if (!maybeDeviceType.has_value()) {
+        const auto& [message, code] = maybeDeviceType.error();
+        LOG(ERROR) << "adapter::Device::getType failed with " << code << ": " << message;
+        cb(V1_2::utils::convert(code).value(), {});
+    } else {
+        cb(V1_0::ErrorStatus::NONE, maybeDeviceType.value());
+    }
+    return Void();
+}
+
+Return<void> Device::getSupportedExtensions(getSupportedExtensions_cb cb) {
+    const auto maybeSupportedExtensions = V1_2::utils::convert(kDevice->getSupportedExtensions());
+    if (!maybeSupportedExtensions.has_value()) {
+        const auto& [message, code] = maybeSupportedExtensions.error();
+        LOG(ERROR) << "adapter::Device::getSupportedExtensions failed with " << code << ": "
+                   << message;
+        cb(V1_2::utils::convert(code).value(), {});
+    } else {
+        cb(V1_0::ErrorStatus::NONE, maybeSupportedExtensions.value());
+    }
+    return Void();
+}
+
+Return<void> Device::getSupportedOperations(const V1_0::Model& model,
+                                            getSupportedOperations_cb cb) {
+    const auto result = adapter::getSupportedOperations(kDevice, model);
+    if (!result.has_value()) {
+        const auto& [message, code] = result.error();
+        LOG(ERROR) << "adapter::Device::getSupportedOperations_1_0 failed with " << code << ": "
+                   << message;
+        cb(V1_0::utils::convert(code).value(), {});
+    } else {
+        cb(V1_0::ErrorStatus::NONE, result.value());
+    }
+    return Void();
+}
+
+Return<void> Device::getSupportedOperations_1_1(const V1_1::Model& model,
+                                                getSupportedOperations_1_1_cb cb) {
+    const auto result = adapter::getSupportedOperations(kDevice, model);
+    if (!result.has_value()) {
+        const auto& [message, code] = result.error();
+        LOG(ERROR) << "adapter::Device::getSupportedOperations_1_1 failed with " << code << ": "
+                   << message;
+        cb(V1_1::utils::convert(code).value(), {});
+    } else {
+        cb(V1_0::ErrorStatus::NONE, result.value());
+    }
+    return Void();
+}
+
+Return<void> Device::getSupportedOperations_1_2(const V1_2::Model& model,
+                                                getSupportedOperations_1_2_cb cb) {
+    const auto result = adapter::getSupportedOperations(kDevice, model);
+    if (!result.has_value()) {
+        const auto& [message, code] = result.error();
+        LOG(ERROR) << "adapter::Device::getSupportedOperations_1_2 failed with " << code << ": "
+                   << message;
+        cb(V1_2::utils::convert(code).value(), {});
+    } else {
+        cb(V1_0::ErrorStatus::NONE, result.value());
+    }
+    return Void();
+}
+
+Return<void> Device::getSupportedOperations_1_3(const V1_3::Model& model,
+                                                getSupportedOperations_1_3_cb cb) {
+    const auto result = adapter::getSupportedOperations(kDevice, model);
+    if (!result.has_value()) {
+        const auto& [message, code] = result.error();
+        LOG(ERROR) << "adapter::Device::getSupportedOperations_1_3 failed with " << code << ": "
+                   << message;
+        cb(V1_3::utils::convert(code).value(), {});
+    } else {
+        cb(V1_3::ErrorStatus::NONE, result.value());
+    }
+    return Void();
+}
+
+Return<void> Device::getNumberOfCacheFilesNeeded(getNumberOfCacheFilesNeeded_cb cb) {
+    const auto [numModelCache, numDataCache] = kDevice->getNumberOfCacheFilesNeeded();
+    cb(V1_0::ErrorStatus::NONE, numModelCache, numDataCache);
+    return Void();
+}
+
+Return<V1_0::ErrorStatus> Device::prepareModel(const V1_0::Model& model,
+                                               const sp<V1_0::IPreparedModelCallback>& callback) {
+    auto result = adapter::prepareModel(kDevice, kExecutor, model, callback);
+    if (!result.has_value()) {
+        auto [message, code] = std::move(result).error();
+        LOG(ERROR) << "adapter::Device::prepareModel failed with " << code << ": " << message;
+        notify(callback.get(), code, nullptr);
+        return V1_0::utils::convert(code).value();
+    }
+    return V1_0::ErrorStatus::NONE;
+}
+
+Return<V1_0::ErrorStatus> Device::prepareModel_1_1(
+        const V1_1::Model& model, V1_1::ExecutionPreference preference,
+        const sp<V1_0::IPreparedModelCallback>& callback) {
+    auto result = adapter::prepareModel_1_1(kDevice, kExecutor, model, preference, callback);
+    if (!result.has_value()) {
+        auto [message, code] = std::move(result).error();
+        LOG(ERROR) << "adapter::Device::prepareModel_1_1 failed with " << code << ": " << message;
+        notify(callback.get(), code, nullptr);
+        return V1_1::utils::convert(code).value();
+    }
+    return V1_0::ErrorStatus::NONE;
+}
+
+Return<V1_0::ErrorStatus> Device::prepareModel_1_2(
+        const V1_2::Model& model, V1_1::ExecutionPreference preference,
+        const hidl_vec<hidl_handle>& modelCache, const hidl_vec<hidl_handle>& dataCache,
+        const CacheToken& token, const sp<V1_2::IPreparedModelCallback>& callback) {
+    auto result = adapter::prepareModel_1_2(kDevice, kExecutor, model, preference, modelCache,
+                                            dataCache, token, callback);
+    if (!result.has_value()) {
+        auto [message, code] = std::move(result).error();
+        LOG(ERROR) << "adapter::Device::prepareModel_1_2 failed with " << code << ": " << message;
+        notify(callback.get(), code, nullptr);
+        return V1_2::utils::convert(code).value();
+    }
+    return V1_0::ErrorStatus::NONE;
+}
+
+Return<V1_3::ErrorStatus> Device::prepareModel_1_3(
+        const V1_3::Model& model, V1_1::ExecutionPreference preference, V1_3::Priority priority,
+        const V1_3::OptionalTimePoint& deadline, const hidl_vec<hidl_handle>& modelCache,
+        const hidl_vec<hidl_handle>& dataCache, const CacheToken& token,
+        const sp<V1_3::IPreparedModelCallback>& callback) {
+    auto result = adapter::prepareModel_1_3(kDevice, kExecutor, model, preference, priority,
+                                            deadline, modelCache, dataCache, token, callback);
+    if (!result.has_value()) {
+        auto [message, code] = std::move(result).error();
+        LOG(ERROR) << "adapter::Device::prepareModel_1_3 failed with " << code << ": " << message;
+        notify(callback.get(), code, nullptr);
+        return V1_3::utils::convert(code).value();
+    }
+    return V1_3::ErrorStatus::NONE;
+}
+
+Return<V1_0::ErrorStatus> Device::prepareModelFromCache(
+        const hidl_vec<hidl_handle>& modelCache, const hidl_vec<hidl_handle>& dataCache,
+        const CacheToken& token, const sp<V1_2::IPreparedModelCallback>& callback) {
+    auto result = adapter::prepareModelFromCache(kDevice, kExecutor, modelCache, dataCache, token,
+                                                 callback);
+    if (!result.has_value()) {
+        auto [message, code] = std::move(result).error();
+        LOG(ERROR) << "adapter::Device::prepareModelFromCache failed with " << code << ": "
+                   << message;
+        notify(callback.get(), code, nullptr);
+        return V1_2::utils::convert(code).value();
+    }
+    return V1_0::ErrorStatus::NONE;
+}
+
+Return<V1_3::ErrorStatus> Device::prepareModelFromCache_1_3(
+        const V1_3::OptionalTimePoint& deadline, const hidl_vec<hidl_handle>& modelCache,
+        const hidl_vec<hidl_handle>& dataCache, const CacheToken& token,
+        const sp<V1_3::IPreparedModelCallback>& callback) {
+    auto result = adapter::prepareModelFromCache_1_3(kDevice, kExecutor, deadline, modelCache,
+                                                     dataCache, token, callback);
+    if (!result.has_value()) {
+        auto [message, code] = std::move(result).error();
+        LOG(ERROR) << "adapter::Device::prepareModelFromCache_1_3 failed with " << code << ": "
+                   << message;
+        notify(callback.get(), code, nullptr);
+        return V1_3::utils::convert(code).value();
+    }
+    return V1_3::ErrorStatus::NONE;
+}
+
+Return<V1_0::DeviceStatus> Device::getStatus() {
+    return V1_0::DeviceStatus::AVAILABLE;
+}
+
+Return<void> Device::allocate(const V1_3::BufferDesc& desc,
+                              const hidl_vec<sp<V1_3::IPreparedModel>>& preparedModels,
+                              const hidl_vec<V1_3::BufferRole>& inputRoles,
+                              const hidl_vec<V1_3::BufferRole>& outputRoles, allocate_cb cb) {
+    auto result = adapter::allocate(kDevice, desc, preparedModels, inputRoles, outputRoles);
+    if (!result.has_value()) {
+        const auto [message, code] = std::move(result).error();
+        LOG(ERROR) << "adapter::Device::allocate failed with " << code << ": " << message;
+        cb(V1_3::utils::convert(code).value(), nullptr, /*token=*/0);
+        return Void();
+    }
+    auto [buffer, token] = std::move(result).value();
+    cb(V1_3::ErrorStatus::NONE, buffer, token);
+    return Void();
+}
+
+}  // namespace android::hardware::neuralnetworks::adapter
diff --git a/neuralnetworks/utils/adapter/hidl/src/PreparedModel.cpp b/neuralnetworks/utils/adapter/hidl/src/PreparedModel.cpp
new file mode 100644
index 0000000..3570a74
--- /dev/null
+++ b/neuralnetworks/utils/adapter/hidl/src/PreparedModel.cpp
@@ -0,0 +1,409 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "PreparedModel.h"
+
+#include "Burst.h"
+
+#include <android-base/logging.h>
+#include <android/hardware/neuralnetworks/1.0/IExecutionCallback.h>
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware/neuralnetworks/1.2/IBurstCallback.h>
+#include <android/hardware/neuralnetworks/1.2/IExecutionCallback.h>
+#include <android/hardware/neuralnetworks/1.2/types.h>
+#include <android/hardware/neuralnetworks/1.3/IExecutionCallback.h>
+#include <android/hardware/neuralnetworks/1.3/IFencedExecutionCallback.h>
+#include <android/hardware/neuralnetworks/1.3/IPreparedModel.h>
+#include <android/hardware/neuralnetworks/1.3/types.h>
+#include <nnapi/IPreparedModel.h>
+#include <nnapi/TypeUtils.h>
+#include <nnapi/Types.h>
+#include <nnapi/Validation.h>
+#include <nnapi/hal/1.0/Utils.h>
+#include <nnapi/hal/1.2/Utils.h>
+#include <nnapi/hal/1.3/Conversions.h>
+#include <nnapi/hal/1.3/Utils.h>
+
+#include <memory>
+#include <thread>
+
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
+// lifetimes across processes and for protecting asynchronous calls across HIDL.
+
+namespace android::hardware::neuralnetworks::adapter {
+namespace {
+
+template <typename Type>
+auto convertInput(const Type& object) -> decltype(nn::convert(std::declval<Type>())) {
+    auto result = nn::convert(object);
+    if (!result.has_value()) {
+        result.error().code = nn::ErrorStatus::INVALID_ARGUMENT;
+    }
+    return result;
+}
+
+class FencedExecutionCallback final : public V1_3::IFencedExecutionCallback {
+  public:
+    explicit FencedExecutionCallback(const nn::ExecuteFencedInfoCallback& callback)
+        : kCallback(callback) {
+        CHECK(callback != nullptr);
+    }
+
+    Return<void> getExecutionInfo(getExecutionInfo_cb cb) override {
+        const auto result = kCallback();
+        if (!result.has_value()) {
+            const auto& [message, code] = result.error();
+            const auto status =
+                    V1_3::utils::convert(code).value_or(V1_3::ErrorStatus::GENERAL_FAILURE);
+            LOG(ERROR) << message;
+            cb(status, V1_2::utils::kNoTiming, V1_2::utils::kNoTiming);
+            return Void();
+        }
+        const auto [timingLaunched, timingFenced] = result.value();
+        const auto hidlTimingLaunched = V1_3::utils::convert(timingLaunched).value();
+        const auto hidlTimingFenced = V1_3::utils::convert(timingFenced).value();
+        cb(V1_3::ErrorStatus::NONE, hidlTimingLaunched, hidlTimingFenced);
+        return Void();
+    }
+
+  private:
+    const nn::ExecuteFencedInfoCallback kCallback;
+};
+
+using ExecutionResult = nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>;
+
+void notify(V1_0::IExecutionCallback* callback, nn::ErrorStatus status,
+            const std::vector<nn::OutputShape>& /*outputShapes*/, const nn::Timing& /*timing*/) {
+    if (callback != nullptr) {
+        const auto hidlStatus = V1_0::utils::convert(status).value();
+        const auto ret = callback->notify(hidlStatus);
+        if (!ret.isOk()) {
+            LOG(ERROR) << "V1_0::IExecutionCallback::notify failed with " << ret.description();
+        }
+    }
+}
+
+void notify(V1_2::IExecutionCallback* callback, nn::ErrorStatus status,
+            const std::vector<nn::OutputShape>& outputShapes, const nn::Timing& timing) {
+    if (callback != nullptr) {
+        const auto hidlStatus = V1_2::utils::convert(status).value();
+        const auto hidlOutputShapes = V1_2::utils::convert(outputShapes).value();
+        const auto hidlTiming = V1_2::utils::convert(timing).value();
+        const auto ret = callback->notify_1_2(hidlStatus, hidlOutputShapes, hidlTiming);
+        if (!ret.isOk()) {
+            LOG(ERROR) << "V1_2::IExecutionCallback::notify_1_2 failed with " << ret.description();
+        }
+    }
+}
+
+void notify(V1_3::IExecutionCallback* callback, nn::ErrorStatus status,
+            const std::vector<nn::OutputShape>& outputShapes, const nn::Timing& timing) {
+    if (callback != nullptr) {
+        const auto hidlStatus = V1_3::utils::convert(status).value();
+        const auto hidlOutputShapes = V1_3::utils::convert(outputShapes).value();
+        const auto hidlTiming = V1_3::utils::convert(timing).value();
+        const auto ret = callback->notify_1_3(hidlStatus, hidlOutputShapes, hidlTiming);
+        if (!ret.isOk()) {
+            LOG(ERROR) << "V1_3::IExecutionCallback::notify_1_3 failed with " << ret.description();
+        }
+    }
+}
+
+template <typename CallbackType>
+void notify(CallbackType* callback, ExecutionResult result) {
+    if (!result.has_value()) {
+        const auto [message, status, outputShapes] = std::move(result).error();
+        LOG(ERROR) << message;
+        notify(callback, status, outputShapes, {});
+    } else {
+        const auto [outputShapes, timing] = std::move(result).value();
+        notify(callback, nn::ErrorStatus::NONE, outputShapes, timing);
+    }
+}
+
+nn::GeneralResult<void> execute(const nn::SharedPreparedModel& preparedModel,
+                                const V1_0::Request& request,
+                                const sp<V1_0::IExecutionCallback>& callback) {
+    if (callback.get() == nullptr) {
+        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
+    }
+
+    const auto nnRequest = NN_TRY(convertInput(request));
+
+    auto result = preparedModel->execute(nnRequest, nn::MeasureTiming::NO, {}, {}, {}, {});
+
+    if (!result.ok() && result.error().code == nn::ErrorStatus::INVALID_ARGUMENT) {
+        const auto& [message, code, outputShapes] = result.error();
+        return nn::error(code) << message;
+    }
+
+    notify(callback.get(), std::move(result));
+    return {};
+}
+
+nn::GeneralResult<void> execute_1_2(const nn::SharedPreparedModel& preparedModel,
+                                    const V1_0::Request& request, V1_2::MeasureTiming measure,
+                                    const sp<V1_2::IExecutionCallback>& callback) {
+    if (callback.get() == nullptr) {
+        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
+    }
+
+    const auto nnRequest = NN_TRY(convertInput(request));
+    const auto nnMeasure = NN_TRY(convertInput(measure));
+
+    auto result = preparedModel->execute(nnRequest, nnMeasure, {}, {}, {}, {});
+
+    if (!result.ok() && result.error().code == nn::ErrorStatus::INVALID_ARGUMENT) {
+        const auto& [message, code, outputShapes] = result.error();
+        return nn::error(code) << message;
+    }
+
+    notify(callback.get(), std::move(result));
+    return {};
+}
+
+nn::GeneralResult<void> execute_1_3(const nn::SharedPreparedModel& preparedModel,
+                                    const V1_3::Request& request, V1_2::MeasureTiming measure,
+                                    const V1_3::OptionalTimePoint& deadline,
+                                    const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
+                                    const sp<V1_3::IExecutionCallback>& callback) {
+    if (callback.get() == nullptr) {
+        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
+    }
+
+    const auto nnRequest = NN_TRY(convertInput(request));
+    const auto nnMeasure = NN_TRY(convertInput(measure));
+    const auto nnDeadline = NN_TRY(convertInput(deadline));
+    const auto nnLoopTimeoutDuration = NN_TRY(convertInput(loopTimeoutDuration));
+
+    auto result =
+            preparedModel->execute(nnRequest, nnMeasure, nnDeadline, nnLoopTimeoutDuration, {}, {});
+
+    if (!result.ok() && result.error().code == nn::ErrorStatus::INVALID_ARGUMENT) {
+        const auto& [message, code, outputShapes] = result.error();
+        return nn::error(code) << message;
+    }
+
+    notify(callback.get(), std::move(result));
+    return {};
+}
+
+nn::ExecutionResult<std::pair<hidl_vec<V1_2::OutputShape>, V1_2::Timing>> executeSynchronously(
+        const nn::SharedPreparedModel& preparedModel, const V1_0::Request& request,
+        V1_2::MeasureTiming measure) {
+    const auto nnRequest = NN_TRY(convertInput(request));
+    const auto nnMeasure = NN_TRY(convertInput(measure));
+
+    const auto [outputShapes, timing] =
+            NN_TRY(preparedModel->execute(nnRequest, nnMeasure, {}, {}, {}, {}));
+
+    auto hidlOutputShapes = NN_TRY(V1_2::utils::convert(outputShapes));
+    const auto hidlTiming = NN_TRY(V1_2::utils::convert(timing));
+    return std::make_pair(std::move(hidlOutputShapes), hidlTiming);
+}
+
+nn::ExecutionResult<std::pair<hidl_vec<V1_2::OutputShape>, V1_2::Timing>> executeSynchronously_1_3(
+        const nn::SharedPreparedModel& preparedModel, const V1_3::Request& request,
+        V1_2::MeasureTiming measure, const V1_3::OptionalTimePoint& deadline,
+        const V1_3::OptionalTimeoutDuration& loopTimeoutDuration) {
+    const auto nnRequest = NN_TRY(convertInput(request));
+    const auto nnMeasure = NN_TRY(convertInput(measure));
+    const auto nnDeadline = NN_TRY(convertInput(deadline));
+    const auto nnLoopTimeoutDuration = NN_TRY(convertInput(loopTimeoutDuration));
+
+    const auto [outputShapes, timing] = NN_TRY(preparedModel->execute(
+            nnRequest, nnMeasure, nnDeadline, nnLoopTimeoutDuration, {}, {}));
+
+    auto hidlOutputShapes = NN_TRY(V1_3::utils::convert(outputShapes));
+    const auto hidlTiming = NN_TRY(V1_3::utils::convert(timing));
+    return std::make_pair(std::move(hidlOutputShapes), hidlTiming);
+}
+
+nn::GeneralResult<std::vector<nn::SyncFence>> convertSyncFences(
+        const hidl_vec<hidl_handle>& handles) {
+    auto nnHandles = NN_TRY(convertInput(handles));
+    std::vector<nn::SyncFence> syncFences;
+    syncFences.reserve(handles.size());
+    for (auto&& handle : nnHandles) {
+        if (auto syncFence = nn::SyncFence::create(std::move(handle)); !syncFence.ok()) {
+            return nn::error(nn::ErrorStatus::INVALID_ARGUMENT) << std::move(syncFence).error();
+        } else {
+            syncFences.push_back(std::move(syncFence).value());
+        }
+    }
+    return syncFences;
+}
+
+nn::GeneralResult<sp<V1_2::IBurstContext>> configureExecutionBurst(
+        const nn::SharedPreparedModel& preparedModel, const sp<V1_2::IBurstCallback>& callback,
+        const MQDescriptorSync<V1_2::FmqRequestDatum>& requestChannel,
+        const MQDescriptorSync<V1_2::FmqResultDatum>& resultChannel) {
+    auto burstExecutor = NN_TRY(preparedModel->configureExecutionBurst());
+    return Burst::create(callback, requestChannel, resultChannel, std::move(burstExecutor),
+                         V1_2::utils::getBurstServerPollingTimeWindow());
+}
+
+nn::GeneralResult<std::pair<hidl_handle, sp<V1_3::IFencedExecutionCallback>>> executeFenced(
+        const nn::SharedPreparedModel& preparedModel, const V1_3::Request& request,
+        const hidl_vec<hidl_handle>& waitFor, V1_2::MeasureTiming measure,
+        const V1_3::OptionalTimePoint& deadline,
+        const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
+        const V1_3::OptionalTimeoutDuration& duration) {
+    const auto nnRequest = NN_TRY(convertInput(request));
+    const auto nnWaitFor = NN_TRY(convertSyncFences(waitFor));
+    const auto nnMeasure = NN_TRY(convertInput(measure));
+    const auto nnDeadline = NN_TRY(convertInput(deadline));
+    const auto nnLoopTimeoutDuration = NN_TRY(convertInput(loopTimeoutDuration));
+    const auto nnDuration = NN_TRY(convertInput(duration));
+
+    auto [syncFence, executeFencedCallback] =
+            NN_TRY(preparedModel->executeFenced(nnRequest, nnWaitFor, nnMeasure, nnDeadline,
+                                                nnLoopTimeoutDuration, nnDuration, {}, {}));
+
+    auto hidlSyncFence = NN_TRY(V1_3::utils::convert(syncFence.getSharedHandle()));
+    auto hidlExecuteFencedCallback = sp<FencedExecutionCallback>::make(executeFencedCallback);
+    return std::make_pair(std::move(hidlSyncFence), std::move(hidlExecuteFencedCallback));
+}
+
+}  // namespace
+
+PreparedModel::PreparedModel(nn::SharedPreparedModel preparedModel)
+    : kPreparedModel(std::move(preparedModel)) {
+    CHECK(kPreparedModel != nullptr);
+}
+
+nn::SharedPreparedModel PreparedModel::getUnderlyingPreparedModel() const {
+    return kPreparedModel;
+}
+
+Return<V1_0::ErrorStatus> PreparedModel::execute(const V1_0::Request& request,
+                                                 const sp<V1_0::IExecutionCallback>& callback) {
+    auto result = adapter::execute(kPreparedModel, request, callback);
+    if (!result.has_value()) {
+        auto [message, code] = std::move(result).error();
+        LOG(ERROR) << "adapter::PreparedModel::execute failed with " << code << ": " << message;
+        notify(callback.get(), code, {}, {});
+        return V1_0::utils::convert(code).value();
+    }
+    return V1_0::ErrorStatus::NONE;
+}
+
+Return<V1_0::ErrorStatus> PreparedModel::execute_1_2(const V1_0::Request& request,
+                                                     V1_2::MeasureTiming measure,
+                                                     const sp<V1_2::IExecutionCallback>& callback) {
+    auto result = adapter::execute_1_2(kPreparedModel, request, measure, callback);
+    if (!result.has_value()) {
+        auto [message, code] = std::move(result).error();
+        LOG(ERROR) << "adapter::PreparedModel::execute_1_2 failed with " << code << ": " << message;
+        notify(callback.get(), code, {}, {});
+        return V1_2::utils::convert(code).value();
+    }
+    return V1_0::ErrorStatus::NONE;
+}
+
+Return<V1_3::ErrorStatus> PreparedModel::execute_1_3(
+        const V1_3::Request& request, V1_2::MeasureTiming measure,
+        const V1_3::OptionalTimePoint& deadline,
+        const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
+        const sp<V1_3::IExecutionCallback>& callback) {
+    auto result = adapter::execute_1_3(kPreparedModel, request, measure, deadline,
+                                       loopTimeoutDuration, callback);
+    if (!result.has_value()) {
+        auto [message, code] = std::move(result).error();
+        LOG(ERROR) << "adapter::PreparedModel::execute_1_3 failed with " << code << ": " << message;
+        notify(callback.get(), code, {}, {});
+        return V1_3::utils::convert(code).value();
+    }
+    return V1_3::ErrorStatus::NONE;
+}
+
+Return<void> PreparedModel::executeSynchronously(const V1_0::Request& request,
+                                                 V1_2::MeasureTiming measure,
+                                                 executeSynchronously_cb cb) {
+    auto result = adapter::executeSynchronously(kPreparedModel, request, measure);
+    if (!result.has_value()) {
+        auto [message, code, outputShapes] = std::move(result).error();
+        LOG(ERROR) << "adapter::PreparedModel::executeSynchronously failed with " << code << ": "
+                   << message;
+        cb(V1_2::utils::convert(code).value(), V1_2::utils::convert(outputShapes).value(),
+           V1_2::utils::kNoTiming);
+        return Void();
+    }
+    auto [outputShapes, timing] = std::move(result).value();
+    cb(V1_0::ErrorStatus::NONE, outputShapes, timing);
+    return Void();
+}
+
+Return<void> PreparedModel::executeSynchronously_1_3(
+        const V1_3::Request& request, V1_2::MeasureTiming measure,
+        const V1_3::OptionalTimePoint& deadline,
+        const V1_3::OptionalTimeoutDuration& loopTimeoutDuration, executeSynchronously_1_3_cb cb) {
+    auto result = adapter::executeSynchronously_1_3(kPreparedModel, request, measure, deadline,
+                                                    loopTimeoutDuration);
+    if (!result.has_value()) {
+        auto [message, code, outputShapes] = std::move(result).error();
+        LOG(ERROR) << "adapter::PreparedModel::executeSynchronously_1_3 failed with " << code
+                   << ": " << message;
+        cb(V1_3::utils::convert(code).value(), V1_3::utils::convert(outputShapes).value(),
+           V1_2::utils::kNoTiming);
+        return Void();
+    }
+    auto [outputShapes, timing] = std::move(result).value();
+    cb(V1_3::ErrorStatus::NONE, outputShapes, timing);
+    return Void();
+}
+
+Return<void> PreparedModel::configureExecutionBurst(
+        const sp<V1_2::IBurstCallback>& callback,
+        const MQDescriptorSync<V1_2::FmqRequestDatum>& requestChannel,
+        const MQDescriptorSync<V1_2::FmqResultDatum>& resultChannel,
+        configureExecutionBurst_cb cb) {
+    auto result = adapter::configureExecutionBurst(kPreparedModel, callback, requestChannel,
+                                                   resultChannel);
+    if (!result.has_value()) {
+        auto [message, code] = std::move(result).error();
+        LOG(ERROR) << "adapter::PreparedModel::configureExecutionBurst failed with " << code << ": "
+                   << message;
+        cb(V1_2::utils::convert(code).value(), nullptr);
+        return Void();
+    }
+    const auto burstContext = std::move(result).value();
+    cb(V1_0::ErrorStatus::NONE, burstContext);
+    return Void();
+}
+
+Return<void> PreparedModel::executeFenced(const V1_3::Request& request,
+                                          const hidl_vec<hidl_handle>& waitFor,
+                                          V1_2::MeasureTiming measure,
+                                          const V1_3::OptionalTimePoint& deadline,
+                                          const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
+                                          const V1_3::OptionalTimeoutDuration& duration,
+                                          executeFenced_cb callback) {
+    auto result = adapter::executeFenced(kPreparedModel, request, waitFor, measure, deadline,
+                                         loopTimeoutDuration, duration);
+    if (!result.has_value()) {
+        auto [message, code] = std::move(result).error();
+        LOG(ERROR) << "adapter::PreparedModel::executeFenced failed with " << code << ": "
+                   << message;
+        callback(V1_3::utils::convert(code).value(), {}, nullptr);
+        return Void();
+    }
+    auto [syncFence, executeFencedCallback] = std::move(result).value();
+    callback(V1_3::ErrorStatus::NONE, syncFence, executeFencedCallback);
+    return Void();
+}
+
+}  // namespace android::hardware::neuralnetworks::adapter
diff --git a/neuralnetworks/utils/adapter/include/nnapi/hal/Adapter.h b/neuralnetworks/utils/adapter/include/nnapi/hal/Adapter.h
deleted file mode 100644
index da00a09..0000000
--- a/neuralnetworks/utils/adapter/include/nnapi/hal/Adapter.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_ADAPTER_H
-#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_ADAPTER_H
-
-#include <android/hardware/neuralnetworks/1.3/IDevice.h>
-#include <nnapi/IDevice.h>
-#include <nnapi/Types.h>
-#include <sys/types.h>
-#include <functional>
-#include <memory>
-
-// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
-// lifetimes across processes and for protecting asynchronous calls across HIDL.
-
-namespace android::hardware::neuralnetworks::adapter {
-
-/**
- * A self-contained unit of work to be executed.
- */
-using Task = std::function<void()>;
-
-/**
- * A type-erased executor which executes a task asynchronously.
- *
- * This executor is also provided with an Application ID (Android User ID) and an optional deadline
- * for when the caller expects is the upper bound for the amount of time to complete the task.
- */
-using Executor = std::function<void(Task, uid_t, nn::OptionalTimePoint)>;
-
-/**
- * Adapt an NNAPI canonical interface object to a HIDL NN HAL interface object.
- *
- * The IPreparedModel object created from IDevice::prepareModel or IDevice::preparedModelFromCache
- * must return "const nn::Model*" from IPreparedModel::getUnderlyingResource().
- *
- * @param device NNAPI canonical IDevice interface object to be adapted.
- * @param executor Type-erased executor to handle executing tasks asynchronously.
- * @return HIDL NN HAL IDevice interface object.
- */
-sp<V1_3::IDevice> adapt(nn::SharedDevice device, Executor executor);
-
-/**
- * Adapt an NNAPI canonical interface object to a HIDL NN HAL interface object.
- *
- * The IPreparedModel object created from IDevice::prepareModel or IDevice::preparedModelFromCache
- * must return "const nn::Model*" from IPreparedModel::getUnderlyingResource().
- *
- * This function uses a default executor, which will execute tasks from a detached thread.
- *
- * @param device NNAPI canonical IDevice interface object to be adapted.
- * @return HIDL NN HAL IDevice interface object.
- */
-sp<V1_3::IDevice> adapt(nn::SharedDevice device);
-
-}  // namespace android::hardware::neuralnetworks::adapter
-
-#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_ADAPTER_H
diff --git a/neuralnetworks/utils/adapter/include/nnapi/hal/PreparedModel.h b/neuralnetworks/utils/adapter/include/nnapi/hal/PreparedModel.h
deleted file mode 100644
index 65763b8..0000000
--- a/neuralnetworks/utils/adapter/include/nnapi/hal/PreparedModel.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_PREPARED_MODEL_H
-#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_PREPARED_MODEL_H
-
-#include "nnapi/hal/Adapter.h"
-
-#include <android/hardware/neuralnetworks/1.0/IExecutionCallback.h>
-#include <android/hardware/neuralnetworks/1.0/types.h>
-#include <android/hardware/neuralnetworks/1.2/IBurstCallback.h>
-#include <android/hardware/neuralnetworks/1.2/IExecutionCallback.h>
-#include <android/hardware/neuralnetworks/1.2/types.h>
-#include <android/hardware/neuralnetworks/1.3/IExecutionCallback.h>
-#include <android/hardware/neuralnetworks/1.3/IPreparedModel.h>
-#include <android/hardware/neuralnetworks/1.3/types.h>
-#include <nnapi/IPreparedModel.h>
-#include <nnapi/Types.h>
-#include <memory>
-
-// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
-// lifetimes across processes and for protecting asynchronous calls across HIDL.
-
-namespace android::hardware::neuralnetworks::adapter {
-
-// Class that adapts nn::IPreparedModel to V1_3::IPreparedModel.
-class PreparedModel final : public V1_3::IPreparedModel {
-  public:
-    PreparedModel(nn::SharedPreparedModel preparedModel, Executor executor, uid_t userId);
-
-    Return<V1_0::ErrorStatus> execute(const V1_0::Request& request,
-                                      const sp<V1_0::IExecutionCallback>& callback) override;
-    Return<V1_0::ErrorStatus> execute_1_2(const V1_0::Request& request, V1_2::MeasureTiming measure,
-                                          const sp<V1_2::IExecutionCallback>& callback) override;
-    Return<V1_3::ErrorStatus> execute_1_3(const V1_3::Request& request, V1_2::MeasureTiming measure,
-                                          const V1_3::OptionalTimePoint& deadline,
-                                          const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
-                                          const sp<V1_3::IExecutionCallback>& callback) override;
-    Return<void> executeSynchronously(const V1_0::Request& request, V1_2::MeasureTiming measure,
-                                      executeSynchronously_cb cb) override;
-    Return<void> executeSynchronously_1_3(const V1_3::Request& request, V1_2::MeasureTiming measure,
-                                          const V1_3::OptionalTimePoint& deadline,
-                                          const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
-                                          executeSynchronously_1_3_cb cb) override;
-    Return<void> configureExecutionBurst(
-            const sp<V1_2::IBurstCallback>& callback,
-            const MQDescriptorSync<V1_2::FmqRequestDatum>& requestChannel,
-            const MQDescriptorSync<V1_2::FmqResultDatum>& resultChannel,
-            configureExecutionBurst_cb cb) override;
-    Return<void> executeFenced(const V1_3::Request& request, const hidl_vec<hidl_handle>& waitFor,
-                               V1_2::MeasureTiming measure, const V1_3::OptionalTimePoint& deadline,
-                               const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
-                               const V1_3::OptionalTimeoutDuration& duration,
-                               executeFenced_cb callback) override;
-
-    nn::SharedPreparedModel getUnderlyingPreparedModel() const;
-
-  private:
-    const nn::SharedPreparedModel kPreparedModel;
-    const Executor kExecutor;
-    const uid_t kUserId;
-};
-
-}  // namespace android::hardware::neuralnetworks::adapter
-
-#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_ADAPTER_PREPARED_MODEL_H
diff --git a/neuralnetworks/utils/adapter/src/Adapter.cpp b/neuralnetworks/utils/adapter/src/Adapter.cpp
deleted file mode 100644
index d6f53f0..0000000
--- a/neuralnetworks/utils/adapter/src/Adapter.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 "Adapter.h"
-
-#include "Device.h"
-
-#include <android/hardware/neuralnetworks/1.3/IDevice.h>
-#include <nnapi/IDevice.h>
-#include <nnapi/Types.h>
-#include <sys/types.h>
-
-#include <functional>
-#include <memory>
-#include <thread>
-
-// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
-// lifetimes across processes and for protecting asynchronous calls across HIDL.
-
-namespace android::hardware::neuralnetworks::adapter {
-
-sp<V1_3::IDevice> adapt(nn::SharedDevice device, Executor executor) {
-    return sp<Device>::make(std::move(device), std::move(executor));
-}
-
-sp<V1_3::IDevice> adapt(nn::SharedDevice device) {
-    Executor defaultExecutor = [](Task task, uid_t /*uid*/, nn::OptionalTimePoint /*deadline*/) {
-        std::thread(std::move(task)).detach();
-    };
-    return adapt(std::move(device), std::move(defaultExecutor));
-}
-
-}  // namespace android::hardware::neuralnetworks::adapter
diff --git a/neuralnetworks/utils/adapter/src/Device.cpp b/neuralnetworks/utils/adapter/src/Device.cpp
deleted file mode 100644
index 96142c3..0000000
--- a/neuralnetworks/utils/adapter/src/Device.cpp
+++ /dev/null
@@ -1,556 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 "Device.h"
-
-#include "Buffer.h"
-#include "PreparedModel.h"
-
-#include <android-base/logging.h>
-#include <android/hardware/neuralnetworks/1.0/IPreparedModelCallback.h>
-#include <android/hardware/neuralnetworks/1.0/types.h>
-#include <android/hardware/neuralnetworks/1.1/types.h>
-#include <android/hardware/neuralnetworks/1.2/IPreparedModelCallback.h>
-#include <android/hardware/neuralnetworks/1.2/types.h>
-#include <android/hardware/neuralnetworks/1.3/IDevice.h>
-#include <android/hardware/neuralnetworks/1.3/IPreparedModelCallback.h>
-#include <android/hardware/neuralnetworks/1.3/types.h>
-#include <hwbinder/IPCThreadState.h>
-#include <nnapi/IBuffer.h>
-#include <nnapi/IDevice.h>
-#include <nnapi/IPreparedModel.h>
-#include <nnapi/Result.h>
-#include <nnapi/TypeUtils.h>
-#include <nnapi/Types.h>
-#include <nnapi/hal/1.0/Conversions.h>
-#include <nnapi/hal/1.0/Utils.h>
-#include <nnapi/hal/1.1/Conversions.h>
-#include <nnapi/hal/1.1/Utils.h>
-#include <nnapi/hal/1.2/Conversions.h>
-#include <nnapi/hal/1.2/Utils.h>
-#include <nnapi/hal/1.3/Conversions.h>
-#include <nnapi/hal/1.3/Utils.h>
-#include <sys/types.h>
-
-#include <memory>
-
-// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
-// lifetimes across processes and for protecting asynchronous calls across HIDL.
-
-namespace android::hardware::neuralnetworks::adapter {
-namespace {
-
-template <typename Type>
-auto convertInput(const Type& object) -> decltype(nn::convert(std::declval<Type>())) {
-    auto result = nn::convert(object);
-    if (!result.has_value()) {
-        result.error().code = nn::ErrorStatus::INVALID_ARGUMENT;
-    }
-    return result;
-}
-
-using PrepareModelResult = nn::GeneralResult<nn::SharedPreparedModel>;
-
-sp<PreparedModel> adaptPreparedModel(nn::SharedPreparedModel preparedModel, Executor executor,
-                                     uid_t userId) {
-    if (preparedModel == nullptr) {
-        return nullptr;
-    }
-    return sp<PreparedModel>::make(std::move(preparedModel), std::move(executor), userId);
-}
-
-void notify(V1_0::IPreparedModelCallback* callback, nn::ErrorStatus status,
-            const sp<PreparedModel>& hidlPreparedModel) {
-    if (callback != nullptr) {
-        const auto hidlStatus = V1_0::utils::convert(status).value();
-        const auto ret = callback->notify(hidlStatus, hidlPreparedModel);
-        if (!ret.isOk()) {
-            LOG(ERROR) << "V1_0::IPreparedModelCallback::notify failed with " << ret.description();
-        }
-    }
-}
-
-void notify(V1_2::IPreparedModelCallback* callback, nn::ErrorStatus status,
-            const sp<PreparedModel>& hidlPreparedModel) {
-    if (callback != nullptr) {
-        const auto hidlStatus = V1_2::utils::convert(status).value();
-        const auto ret = callback->notify_1_2(hidlStatus, hidlPreparedModel);
-        if (!ret.isOk()) {
-            LOG(ERROR) << "V1_2::IPreparedModelCallback::notify_1_2 failed with "
-                       << ret.description();
-        }
-    }
-}
-
-void notify(V1_3::IPreparedModelCallback* callback, nn::ErrorStatus status,
-            const sp<PreparedModel>& hidlPreparedModel) {
-    if (callback != nullptr) {
-        const auto hidlStatus = V1_3::utils::convert(status).value();
-        const auto ret = callback->notify_1_3(hidlStatus, hidlPreparedModel);
-        if (!ret.isOk()) {
-            LOG(ERROR) << "V1_3::IPreparedModelCallback::notify_1_3 failed with "
-                       << ret.description();
-        }
-    }
-}
-
-template <typename CallbackType>
-void notify(CallbackType* callback, PrepareModelResult result, Executor executor, uid_t userId) {
-    if (!result.has_value()) {
-        const auto [message, status] = std::move(result).error();
-        LOG(ERROR) << message;
-        notify(callback, status, nullptr);
-    } else {
-        auto preparedModel = std::move(result).value();
-        auto hidlPreparedModel =
-                adaptPreparedModel(std::move(preparedModel), std::move(executor), userId);
-        notify(callback, nn::ErrorStatus::NONE, std::move(hidlPreparedModel));
-    }
-}
-
-template <typename ModelType>
-nn::GeneralResult<hidl_vec<bool>> getSupportedOperations(const nn::SharedDevice& device,
-                                                         const ModelType& model) {
-    const auto nnModel = NN_TRY(convertInput(model));
-    return NN_TRY(device->getSupportedOperations(nnModel));
-}
-
-nn::GeneralResult<void> prepareModel(const nn::SharedDevice& device, const Executor& executor,
-                                     const V1_0::Model& model,
-                                     const sp<V1_0::IPreparedModelCallback>& callback) {
-    if (callback.get() == nullptr) {
-        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
-    }
-
-    auto nnModel = NN_TRY(convertInput(model));
-
-    const uid_t userId = hardware::IPCThreadState::self()->getCallingUid();
-    Task task = [device, nnModel = std::move(nnModel), userId, executor, callback] {
-        auto result = device->prepareModel(nnModel, nn::ExecutionPreference::DEFAULT,
-                                           nn::Priority::DEFAULT, {}, {}, {}, {});
-        notify(callback.get(), std::move(result), executor, userId);
-    };
-    executor(std::move(task), userId, {});
-
-    return {};
-}
-
-nn::GeneralResult<void> prepareModel_1_1(const nn::SharedDevice& device, const Executor& executor,
-                                         const V1_1::Model& model,
-                                         V1_1::ExecutionPreference preference,
-                                         const sp<V1_0::IPreparedModelCallback>& callback) {
-    if (callback.get() == nullptr) {
-        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
-    }
-
-    auto nnModel = NN_TRY(convertInput(model));
-    const auto nnPreference = NN_TRY(convertInput(preference));
-
-    const uid_t userId = hardware::IPCThreadState::self()->getCallingUid();
-    Task task = [device, nnModel = std::move(nnModel), nnPreference, userId, executor, callback] {
-        auto result =
-                device->prepareModel(nnModel, nnPreference, nn::Priority::DEFAULT, {}, {}, {}, {});
-        notify(callback.get(), std::move(result), executor, userId);
-    };
-    executor(std::move(task), userId, {});
-
-    return {};
-}
-
-nn::GeneralResult<void> prepareModel_1_2(const nn::SharedDevice& device, const Executor& executor,
-                                         const V1_2::Model& model,
-                                         V1_1::ExecutionPreference preference,
-                                         const hidl_vec<hidl_handle>& modelCache,
-                                         const hidl_vec<hidl_handle>& dataCache,
-                                         const CacheToken& token,
-                                         const sp<V1_2::IPreparedModelCallback>& callback) {
-    if (callback.get() == nullptr) {
-        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
-    }
-
-    auto nnModel = NN_TRY(convertInput(model));
-    const auto nnPreference = NN_TRY(convertInput(preference));
-    auto nnModelCache = NN_TRY(convertInput(modelCache));
-    auto nnDataCache = NN_TRY(convertInput(dataCache));
-    const auto nnToken = nn::CacheToken(token);
-
-    const uid_t userId = hardware::IPCThreadState::self()->getCallingUid();
-    Task task = [device, nnModel = std::move(nnModel), nnPreference,
-                 nnModelCache = std::move(nnModelCache), nnDataCache = std::move(nnDataCache),
-                 nnToken, userId, executor, callback] {
-        auto result = device->prepareModel(nnModel, nnPreference, nn::Priority::DEFAULT, {},
-                                           nnModelCache, nnDataCache, nnToken);
-        notify(callback.get(), std::move(result), executor, userId);
-    };
-    executor(std::move(task), userId, {});
-
-    return {};
-}
-
-nn::GeneralResult<void> prepareModel_1_3(
-        const nn::SharedDevice& device, const Executor& executor, const V1_3::Model& model,
-        V1_1::ExecutionPreference preference, V1_3::Priority priority,
-        const V1_3::OptionalTimePoint& deadline, const hidl_vec<hidl_handle>& modelCache,
-        const hidl_vec<hidl_handle>& dataCache, const CacheToken& token,
-        const sp<V1_3::IPreparedModelCallback>& callback) {
-    if (callback.get() == nullptr) {
-        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
-    }
-
-    auto nnModel = NN_TRY(convertInput(model));
-    const auto nnPreference = NN_TRY(convertInput(preference));
-    const auto nnPriority = NN_TRY(convertInput(priority));
-    const auto nnDeadline = NN_TRY(convertInput(deadline));
-    auto nnModelCache = NN_TRY(convertInput(modelCache));
-    auto nnDataCache = NN_TRY(convertInput(dataCache));
-    const auto nnToken = nn::CacheToken(token);
-
-    const uid_t userId = hardware::IPCThreadState::self()->getCallingUid();
-    Task task = [device, nnModel = std::move(nnModel), nnPreference, nnPriority, nnDeadline,
-                 nnModelCache = std::move(nnModelCache), nnDataCache = std::move(nnDataCache),
-                 nnToken, userId, executor, callback] {
-        auto result = device->prepareModel(nnModel, nnPreference, nnPriority, nnDeadline,
-                                           nnModelCache, nnDataCache, nnToken);
-        notify(callback.get(), std::move(result), executor, userId);
-    };
-    executor(std::move(task), userId, nnDeadline);
-
-    return {};
-}
-
-nn::GeneralResult<void> prepareModelFromCache(const nn::SharedDevice& device,
-                                              const Executor& executor,
-                                              const hidl_vec<hidl_handle>& modelCache,
-                                              const hidl_vec<hidl_handle>& dataCache,
-                                              const CacheToken& token,
-                                              const sp<V1_2::IPreparedModelCallback>& callback) {
-    if (callback.get() == nullptr) {
-        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
-    }
-
-    auto nnModelCache = NN_TRY(convertInput(modelCache));
-    auto nnDataCache = NN_TRY(convertInput(dataCache));
-    const auto nnToken = nn::CacheToken(token);
-
-    const uid_t userId = hardware::IPCThreadState::self()->getCallingUid();
-    Task task = [device, nnModelCache = std::move(nnModelCache),
-                 nnDataCache = std::move(nnDataCache), nnToken, userId, executor, callback] {
-        auto result = device->prepareModelFromCache({}, nnModelCache, nnDataCache, nnToken);
-        notify(callback.get(), std::move(result), executor, userId);
-    };
-    executor(std::move(task), userId, {});
-
-    return {};
-}
-
-nn::GeneralResult<void> prepareModelFromCache_1_3(
-        const nn::SharedDevice& device, const Executor& executor,
-        const V1_3::OptionalTimePoint& deadline, const hidl_vec<hidl_handle>& modelCache,
-        const hidl_vec<hidl_handle>& dataCache, const CacheToken& token,
-        const sp<V1_3::IPreparedModelCallback>& callback) {
-    if (callback.get() == nullptr) {
-        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
-    }
-
-    const auto nnDeadline = NN_TRY(convertInput(deadline));
-    auto nnModelCache = NN_TRY(convertInput(modelCache));
-    auto nnDataCache = NN_TRY(convertInput(dataCache));
-    const auto nnToken = nn::CacheToken(token);
-
-    const uid_t userId = hardware::IPCThreadState::self()->getCallingUid();
-    auto task = [device, nnDeadline, nnModelCache = std::move(nnModelCache),
-                 nnDataCache = std::move(nnDataCache), nnToken, userId, executor, callback] {
-        auto result = device->prepareModelFromCache(nnDeadline, nnModelCache, nnDataCache, nnToken);
-        notify(callback.get(), std::move(result), executor, userId);
-    };
-    executor(std::move(task), userId, nnDeadline);
-
-    return {};
-}
-
-nn::GeneralResult<nn::SharedPreparedModel> downcast(const sp<V1_3::IPreparedModel>& preparedModel) {
-    if (preparedModel == nullptr) {
-        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "preparedModel is nullptr";
-    }
-    if (preparedModel->isRemote()) {
-        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Cannot convert remote models";
-    }
-
-    // This static_cast is safe because adapter::PreparedModel is the only class that implements
-    // the IPreparedModel interface in the adapter service code.
-    const auto* casted = static_cast<const PreparedModel*>(preparedModel.get());
-    return casted->getUnderlyingPreparedModel();
-}
-
-nn::GeneralResult<std::vector<nn::SharedPreparedModel>> downcastAll(
-        const hidl_vec<sp<V1_3::IPreparedModel>>& preparedModels) {
-    std::vector<nn::SharedPreparedModel> canonical;
-    canonical.reserve(preparedModels.size());
-    for (const auto& preparedModel : preparedModels) {
-        canonical.push_back(NN_TRY(downcast(preparedModel)));
-    }
-    return canonical;
-}
-
-nn::GeneralResult<std::pair<sp<V1_3::IBuffer>, uint32_t>> allocate(
-        const nn::SharedDevice& device, const V1_3::BufferDesc& desc,
-        const hidl_vec<sp<V1_3::IPreparedModel>>& preparedModels,
-        const hidl_vec<V1_3::BufferRole>& inputRoles,
-        const hidl_vec<V1_3::BufferRole>& outputRoles) {
-    auto nnDesc = NN_TRY(convertInput(desc));
-    auto nnPreparedModels = NN_TRY(downcastAll(preparedModels));
-    auto nnInputRoles = NN_TRY(convertInput(inputRoles));
-    auto nnOutputRoles = NN_TRY(convertInput(outputRoles));
-
-    auto buffer = NN_TRY(device->allocate(nnDesc, nnPreparedModels, nnInputRoles, nnOutputRoles));
-
-    const nn::Request::MemoryDomainToken token = buffer->getToken();
-    auto hidlBuffer = sp<Buffer>::make(std::move(buffer));
-    return std::make_pair(std::move(hidlBuffer), static_cast<uint32_t>(token));
-}
-
-}  // namespace
-
-Device::Device(nn::SharedDevice device, Executor executor)
-    : kDevice(std::move(device)), kExecutor(std::move(executor)) {
-    CHECK(kDevice != nullptr);
-    CHECK(kExecutor != nullptr);
-}
-
-Return<void> Device::getCapabilities(getCapabilities_cb cb) {
-    const auto capabilities = V1_0::utils::convert(kDevice->getCapabilities()).value();
-    cb(V1_0::ErrorStatus::NONE, capabilities);
-    return Void();
-}
-
-Return<void> Device::getCapabilities_1_1(getCapabilities_1_1_cb cb) {
-    const auto capabilities = V1_1::utils::convert(kDevice->getCapabilities()).value();
-    cb(V1_0::ErrorStatus::NONE, capabilities);
-    return Void();
-}
-
-Return<void> Device::getCapabilities_1_2(getCapabilities_1_2_cb cb) {
-    const auto capabilities = V1_2::utils::convert(kDevice->getCapabilities()).value();
-    cb(V1_0::ErrorStatus::NONE, capabilities);
-    return Void();
-}
-
-Return<void> Device::getCapabilities_1_3(getCapabilities_1_3_cb cb) {
-    const auto capabilities = V1_3::utils::convert(kDevice->getCapabilities()).value();
-    cb(V1_3::ErrorStatus::NONE, capabilities);
-    return Void();
-}
-
-Return<void> Device::getVersionString(getVersionString_cb cb) {
-    cb(V1_0::ErrorStatus::NONE, kDevice->getVersionString());
-    return Void();
-}
-
-Return<void> Device::getType(getType_cb cb) {
-    const auto maybeDeviceType = V1_2::utils::convert(kDevice->getType());
-    if (!maybeDeviceType.has_value()) {
-        const auto& [message, code] = maybeDeviceType.error();
-        LOG(ERROR) << "adapter::Device::getType failed with " << code << ": " << message;
-        cb(V1_2::utils::convert(code).value(), {});
-    } else {
-        cb(V1_0::ErrorStatus::NONE, maybeDeviceType.value());
-    }
-    return Void();
-}
-
-Return<void> Device::getSupportedExtensions(getSupportedExtensions_cb cb) {
-    const auto maybeSupportedExtensions = V1_2::utils::convert(kDevice->getSupportedExtensions());
-    if (!maybeSupportedExtensions.has_value()) {
-        const auto& [message, code] = maybeSupportedExtensions.error();
-        LOG(ERROR) << "adapter::Device::getSupportedExtensions failed with " << code << ": "
-                   << message;
-        cb(V1_2::utils::convert(code).value(), {});
-    } else {
-        cb(V1_0::ErrorStatus::NONE, maybeSupportedExtensions.value());
-    }
-    return Void();
-}
-
-Return<void> Device::getSupportedOperations(const V1_0::Model& model,
-                                            getSupportedOperations_cb cb) {
-    const auto result = adapter::getSupportedOperations(kDevice, model);
-    if (!result.has_value()) {
-        const auto& [message, code] = result.error();
-        LOG(ERROR) << "adapter::Device::getSupportedOperations_1_0 failed with " << code << ": "
-                   << message;
-        cb(V1_0::utils::convert(code).value(), {});
-    } else {
-        cb(V1_0::ErrorStatus::NONE, result.value());
-    }
-    return Void();
-}
-
-Return<void> Device::getSupportedOperations_1_1(const V1_1::Model& model,
-                                                getSupportedOperations_1_1_cb cb) {
-    const auto result = adapter::getSupportedOperations(kDevice, model);
-    if (!result.has_value()) {
-        const auto& [message, code] = result.error();
-        LOG(ERROR) << "adapter::Device::getSupportedOperations_1_1 failed with " << code << ": "
-                   << message;
-        cb(V1_1::utils::convert(code).value(), {});
-    } else {
-        cb(V1_0::ErrorStatus::NONE, result.value());
-    }
-    return Void();
-}
-
-Return<void> Device::getSupportedOperations_1_2(const V1_2::Model& model,
-                                                getSupportedOperations_1_2_cb cb) {
-    const auto result = adapter::getSupportedOperations(kDevice, model);
-    if (!result.has_value()) {
-        const auto& [message, code] = result.error();
-        LOG(ERROR) << "adapter::Device::getSupportedOperations_1_2 failed with " << code << ": "
-                   << message;
-        cb(V1_2::utils::convert(code).value(), {});
-    } else {
-        cb(V1_0::ErrorStatus::NONE, result.value());
-    }
-    return Void();
-}
-
-Return<void> Device::getSupportedOperations_1_3(const V1_3::Model& model,
-                                                getSupportedOperations_1_3_cb cb) {
-    const auto result = adapter::getSupportedOperations(kDevice, model);
-    if (!result.has_value()) {
-        const auto& [message, code] = result.error();
-        LOG(ERROR) << "adapter::Device::getSupportedOperations_1_3 failed with " << code << ": "
-                   << message;
-        cb(V1_3::utils::convert(code).value(), {});
-    } else {
-        cb(V1_3::ErrorStatus::NONE, result.value());
-    }
-    return Void();
-}
-
-Return<void> Device::getNumberOfCacheFilesNeeded(getNumberOfCacheFilesNeeded_cb cb) {
-    const auto [numModelCache, numDataCache] = kDevice->getNumberOfCacheFilesNeeded();
-    cb(V1_0::ErrorStatus::NONE, numModelCache, numDataCache);
-    return Void();
-}
-
-Return<V1_0::ErrorStatus> Device::prepareModel(const V1_0::Model& model,
-                                               const sp<V1_0::IPreparedModelCallback>& callback) {
-    auto result = adapter::prepareModel(kDevice, kExecutor, model, callback);
-    if (!result.has_value()) {
-        auto [message, code] = std::move(result).error();
-        LOG(ERROR) << "adapter::Device::prepareModel failed with " << code << ": " << message;
-        notify(callback.get(), code, nullptr);
-        return V1_0::utils::convert(code).value();
-    }
-    return V1_0::ErrorStatus::NONE;
-}
-
-Return<V1_0::ErrorStatus> Device::prepareModel_1_1(
-        const V1_1::Model& model, V1_1::ExecutionPreference preference,
-        const sp<V1_0::IPreparedModelCallback>& callback) {
-    auto result = adapter::prepareModel_1_1(kDevice, kExecutor, model, preference, callback);
-    if (!result.has_value()) {
-        auto [message, code] = std::move(result).error();
-        LOG(ERROR) << "adapter::Device::prepareModel_1_1 failed with " << code << ": " << message;
-        notify(callback.get(), code, nullptr);
-        return V1_1::utils::convert(code).value();
-    }
-    return V1_0::ErrorStatus::NONE;
-}
-
-Return<V1_0::ErrorStatus> Device::prepareModel_1_2(
-        const V1_2::Model& model, V1_1::ExecutionPreference preference,
-        const hidl_vec<hidl_handle>& modelCache, const hidl_vec<hidl_handle>& dataCache,
-        const CacheToken& token, const sp<V1_2::IPreparedModelCallback>& callback) {
-    auto result = adapter::prepareModel_1_2(kDevice, kExecutor, model, preference, modelCache,
-                                            dataCache, token, callback);
-    if (!result.has_value()) {
-        auto [message, code] = std::move(result).error();
-        LOG(ERROR) << "adapter::Device::prepareModel_1_2 failed with " << code << ": " << message;
-        notify(callback.get(), code, nullptr);
-        return V1_2::utils::convert(code).value();
-    }
-    return V1_0::ErrorStatus::NONE;
-}
-
-Return<V1_3::ErrorStatus> Device::prepareModel_1_3(
-        const V1_3::Model& model, V1_1::ExecutionPreference preference, V1_3::Priority priority,
-        const V1_3::OptionalTimePoint& deadline, const hidl_vec<hidl_handle>& modelCache,
-        const hidl_vec<hidl_handle>& dataCache, const CacheToken& token,
-        const sp<V1_3::IPreparedModelCallback>& callback) {
-    auto result = adapter::prepareModel_1_3(kDevice, kExecutor, model, preference, priority,
-                                            deadline, modelCache, dataCache, token, callback);
-    if (!result.has_value()) {
-        auto [message, code] = std::move(result).error();
-        LOG(ERROR) << "adapter::Device::prepareModel_1_3 failed with " << code << ": " << message;
-        notify(callback.get(), code, nullptr);
-        return V1_3::utils::convert(code).value();
-    }
-    return V1_3::ErrorStatus::NONE;
-}
-
-Return<V1_0::ErrorStatus> Device::prepareModelFromCache(
-        const hidl_vec<hidl_handle>& modelCache, const hidl_vec<hidl_handle>& dataCache,
-        const CacheToken& token, const sp<V1_2::IPreparedModelCallback>& callback) {
-    auto result = adapter::prepareModelFromCache(kDevice, kExecutor, modelCache, dataCache, token,
-                                                 callback);
-    if (!result.has_value()) {
-        auto [message, code] = std::move(result).error();
-        LOG(ERROR) << "adapter::Device::prepareModelFromCache failed with " << code << ": "
-                   << message;
-        notify(callback.get(), code, nullptr);
-        return V1_2::utils::convert(code).value();
-    }
-    return V1_0::ErrorStatus::NONE;
-}
-
-Return<V1_3::ErrorStatus> Device::prepareModelFromCache_1_3(
-        const V1_3::OptionalTimePoint& deadline, const hidl_vec<hidl_handle>& modelCache,
-        const hidl_vec<hidl_handle>& dataCache, const CacheToken& token,
-        const sp<V1_3::IPreparedModelCallback>& callback) {
-    auto result = adapter::prepareModelFromCache_1_3(kDevice, kExecutor, deadline, modelCache,
-                                                     dataCache, token, callback);
-    if (!result.has_value()) {
-        auto [message, code] = std::move(result).error();
-        LOG(ERROR) << "adapter::Device::prepareModelFromCache_1_3 failed with " << code << ": "
-                   << message;
-        notify(callback.get(), code, nullptr);
-        return V1_3::utils::convert(code).value();
-    }
-    return V1_3::ErrorStatus::NONE;
-}
-
-Return<V1_0::DeviceStatus> Device::getStatus() {
-    return V1_0::DeviceStatus::AVAILABLE;
-}
-
-Return<void> Device::allocate(const V1_3::BufferDesc& desc,
-                              const hidl_vec<sp<V1_3::IPreparedModel>>& preparedModels,
-                              const hidl_vec<V1_3::BufferRole>& inputRoles,
-                              const hidl_vec<V1_3::BufferRole>& outputRoles, allocate_cb cb) {
-    auto result = adapter::allocate(kDevice, desc, preparedModels, inputRoles, outputRoles);
-    if (!result.has_value()) {
-        const auto [message, code] = std::move(result).error();
-        LOG(ERROR) << "adapter::Device::allocate failed with " << code << ": " << message;
-        cb(V1_3::utils::convert(code).value(), nullptr, /*token=*/0);
-        return Void();
-    }
-    auto [buffer, token] = std::move(result).value();
-    cb(V1_3::ErrorStatus::NONE, buffer, token);
-    return Void();
-}
-
-}  // namespace android::hardware::neuralnetworks::adapter
diff --git a/neuralnetworks/utils/adapter/src/PreparedModel.cpp b/neuralnetworks/utils/adapter/src/PreparedModel.cpp
deleted file mode 100644
index 8968c2c..0000000
--- a/neuralnetworks/utils/adapter/src/PreparedModel.cpp
+++ /dev/null
@@ -1,417 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 "PreparedModel.h"
-
-#include <ExecutionBurstServer.h>
-#include <android-base/logging.h>
-#include <android/hardware/neuralnetworks/1.0/IExecutionCallback.h>
-#include <android/hardware/neuralnetworks/1.0/types.h>
-#include <android/hardware/neuralnetworks/1.2/IBurstCallback.h>
-#include <android/hardware/neuralnetworks/1.2/IExecutionCallback.h>
-#include <android/hardware/neuralnetworks/1.2/types.h>
-#include <android/hardware/neuralnetworks/1.3/IExecutionCallback.h>
-#include <android/hardware/neuralnetworks/1.3/IFencedExecutionCallback.h>
-#include <android/hardware/neuralnetworks/1.3/IPreparedModel.h>
-#include <android/hardware/neuralnetworks/1.3/types.h>
-#include <hwbinder/IPCThreadState.h>
-#include <nnapi/IPreparedModel.h>
-#include <nnapi/TypeUtils.h>
-#include <nnapi/Types.h>
-#include <nnapi/Validation.h>
-#include <nnapi/hal/1.0/Utils.h>
-#include <nnapi/hal/1.2/Utils.h>
-#include <nnapi/hal/1.3/Conversions.h>
-#include <nnapi/hal/1.3/Utils.h>
-#include <nnapi/hal/HandleError.h>
-#include <sys/types.h>
-
-#include <memory>
-#include <thread>
-
-// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
-// lifetimes across processes and for protecting asynchronous calls across HIDL.
-
-namespace android::hardware::neuralnetworks::adapter {
-namespace {
-
-template <typename Type>
-auto convertInput(const Type& object) -> decltype(nn::convert(std::declval<Type>())) {
-    auto result = nn::convert(object);
-    if (!result.has_value()) {
-        result.error().code = nn::ErrorStatus::INVALID_ARGUMENT;
-    }
-    return result;
-}
-
-class FencedExecutionCallback final : public V1_3::IFencedExecutionCallback {
-  public:
-    explicit FencedExecutionCallback(const nn::ExecuteFencedInfoCallback& callback)
-        : kCallback(callback) {
-        CHECK(callback != nullptr);
-    }
-
-    Return<void> getExecutionInfo(getExecutionInfo_cb cb) override {
-        const auto result = kCallback();
-        if (!result.has_value()) {
-            const auto& [message, code] = result.error();
-            const auto status =
-                    V1_3::utils::convert(code).value_or(V1_3::ErrorStatus::GENERAL_FAILURE);
-            LOG(ERROR) << message;
-            cb(status, V1_2::utils::kNoTiming, V1_2::utils::kNoTiming);
-            return Void();
-        }
-        const auto [timingLaunched, timingFenced] = result.value();
-        const auto hidlTimingLaunched = V1_3::utils::convert(timingLaunched).value();
-        const auto hidlTimingFenced = V1_3::utils::convert(timingFenced).value();
-        cb(V1_3::ErrorStatus::NONE, hidlTimingLaunched, hidlTimingFenced);
-        return Void();
-    }
-
-  private:
-    const nn::ExecuteFencedInfoCallback kCallback;
-};
-
-using ExecutionResult = nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>;
-
-void notify(V1_0::IExecutionCallback* callback, nn::ErrorStatus status,
-            const std::vector<nn::OutputShape>& /*outputShapes*/, const nn::Timing& /*timing*/) {
-    if (callback != nullptr) {
-        const auto hidlStatus = V1_0::utils::convert(status).value();
-        const auto ret = callback->notify(hidlStatus);
-        if (!ret.isOk()) {
-            LOG(ERROR) << "V1_0::IExecutionCallback::notify failed with " << ret.description();
-        }
-    }
-}
-
-void notify(V1_2::IExecutionCallback* callback, nn::ErrorStatus status,
-            const std::vector<nn::OutputShape>& outputShapes, const nn::Timing& timing) {
-    if (callback != nullptr) {
-        const auto hidlStatus = V1_2::utils::convert(status).value();
-        const auto hidlOutputShapes = V1_2::utils::convert(outputShapes).value();
-        const auto hidlTiming = V1_2::utils::convert(timing).value();
-        const auto ret = callback->notify_1_2(hidlStatus, hidlOutputShapes, hidlTiming);
-        if (!ret.isOk()) {
-            LOG(ERROR) << "V1_2::IExecutionCallback::notify_1_2 failed with " << ret.description();
-        }
-    }
-}
-
-void notify(V1_3::IExecutionCallback* callback, nn::ErrorStatus status,
-            const std::vector<nn::OutputShape>& outputShapes, const nn::Timing& timing) {
-    if (callback != nullptr) {
-        const auto hidlStatus = V1_3::utils::convert(status).value();
-        const auto hidlOutputShapes = V1_3::utils::convert(outputShapes).value();
-        const auto hidlTiming = V1_3::utils::convert(timing).value();
-        const auto ret = callback->notify_1_3(hidlStatus, hidlOutputShapes, hidlTiming);
-        if (!ret.isOk()) {
-            LOG(ERROR) << "V1_3::IExecutionCallback::notify_1_3 failed with " << ret.description();
-        }
-    }
-}
-
-template <typename CallbackType>
-void notify(CallbackType* callback, ExecutionResult result) {
-    if (!result.has_value()) {
-        const auto [message, status, outputShapes] = std::move(result).error();
-        LOG(ERROR) << message;
-        notify(callback, status, outputShapes, {});
-    } else {
-        const auto [outputShapes, timing] = std::move(result).value();
-        notify(callback, nn::ErrorStatus::NONE, outputShapes, timing);
-    }
-}
-
-nn::GeneralResult<void> execute(const nn::SharedPreparedModel& preparedModel, uid_t userId,
-                                const Executor& executor, const V1_0::Request& request,
-                                const sp<V1_0::IExecutionCallback>& callback) {
-    if (callback.get() == nullptr) {
-        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
-    }
-
-    auto nnRequest = NN_TRY(convertInput(request));
-
-    const std::any resource = preparedModel->getUnderlyingResource();
-    if (const auto* model = std::any_cast<const nn::Model*>(&resource)) {
-        CHECK(*model != nullptr);
-        NN_TRY(utils::makeGeneralFailure(nn::validateRequestForModel(nnRequest, **model),
-                                         nn::ErrorStatus::INVALID_ARGUMENT));
-    }
-
-    Task task = [preparedModel, nnRequest = std::move(nnRequest), callback] {
-        auto result = preparedModel->execute(nnRequest, nn::MeasureTiming::NO, {}, {});
-        notify(callback.get(), std::move(result));
-    };
-    executor(std::move(task), userId, {});
-
-    return {};
-}
-
-nn::GeneralResult<void> execute_1_2(const nn::SharedPreparedModel& preparedModel, uid_t userId,
-                                    const Executor& executor, const V1_0::Request& request,
-                                    V1_2::MeasureTiming measure,
-                                    const sp<V1_2::IExecutionCallback>& callback) {
-    if (callback.get() == nullptr) {
-        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
-    }
-
-    auto nnRequest = NN_TRY(convertInput(request));
-    const auto nnMeasure = NN_TRY(convertInput(measure));
-
-    const std::any resource = preparedModel->getUnderlyingResource();
-    if (const auto* model = std::any_cast<const nn::Model*>(&resource)) {
-        CHECK(*model != nullptr);
-        NN_TRY(utils::makeGeneralFailure(nn::validateRequestForModel(nnRequest, **model),
-                                         nn::ErrorStatus::INVALID_ARGUMENT));
-    }
-
-    Task task = [preparedModel, nnRequest = std::move(nnRequest), nnMeasure, callback] {
-        auto result = preparedModel->execute(nnRequest, nnMeasure, {}, {});
-        notify(callback.get(), std::move(result));
-    };
-    executor(std::move(task), userId, {});
-
-    return {};
-}
-
-nn::GeneralResult<void> execute_1_3(const nn::SharedPreparedModel& preparedModel, uid_t userId,
-                                    const Executor& executor, const V1_3::Request& request,
-                                    V1_2::MeasureTiming measure,
-                                    const V1_3::OptionalTimePoint& deadline,
-                                    const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
-                                    const sp<V1_3::IExecutionCallback>& callback) {
-    if (callback.get() == nullptr) {
-        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT) << "Invalid callback";
-    }
-
-    auto nnRequest = NN_TRY(convertInput(request));
-    const auto nnMeasure = NN_TRY(convertInput(measure));
-    const auto nnDeadline = NN_TRY(convertInput(deadline));
-    const auto nnLoopTimeoutDuration = NN_TRY(convertInput(loopTimeoutDuration));
-
-    const std::any resource = preparedModel->getUnderlyingResource();
-    if (const auto* model = std::any_cast<const nn::Model*>(&resource)) {
-        CHECK(*model != nullptr);
-        NN_TRY(utils::makeGeneralFailure(nn::validateRequestForModel(nnRequest, **model),
-                                         nn::ErrorStatus::INVALID_ARGUMENT));
-    }
-
-    Task task = [preparedModel, nnRequest = std::move(nnRequest), nnMeasure, nnDeadline,
-                 nnLoopTimeoutDuration, callback] {
-        auto result =
-                preparedModel->execute(nnRequest, nnMeasure, nnDeadline, nnLoopTimeoutDuration);
-        notify(callback.get(), std::move(result));
-    };
-    executor(std::move(task), userId, nnDeadline);
-
-    return {};
-}
-
-nn::ExecutionResult<std::pair<hidl_vec<V1_2::OutputShape>, V1_2::Timing>> executeSynchronously(
-        const nn::SharedPreparedModel& preparedModel, const V1_0::Request& request,
-        V1_2::MeasureTiming measure) {
-    const auto nnRequest = NN_TRY(utils::makeExecutionFailure(convertInput(request)));
-    const auto nnMeasure = NN_TRY(utils::makeExecutionFailure(convertInput(measure)));
-
-    const auto [outputShapes, timing] =
-            NN_TRY(preparedModel->execute(nnRequest, nnMeasure, {}, {}));
-
-    auto hidlOutputShapes = NN_TRY(utils::makeExecutionFailure(V1_2::utils::convert(outputShapes)));
-    const auto hidlTiming = NN_TRY(utils::makeExecutionFailure(V1_2::utils::convert(timing)));
-    return std::make_pair(std::move(hidlOutputShapes), hidlTiming);
-}
-
-nn::ExecutionResult<std::pair<hidl_vec<V1_2::OutputShape>, V1_2::Timing>> executeSynchronously_1_3(
-        const nn::SharedPreparedModel& preparedModel, const V1_3::Request& request,
-        V1_2::MeasureTiming measure, const V1_3::OptionalTimePoint& deadline,
-        const V1_3::OptionalTimeoutDuration& loopTimeoutDuration) {
-    const auto nnRequest = NN_TRY(utils::makeExecutionFailure(convertInput(request)));
-    const auto nnMeasure = NN_TRY(utils::makeExecutionFailure(convertInput(measure)));
-    const auto nnDeadline = NN_TRY(utils::makeExecutionFailure(convertInput(deadline)));
-    const auto nnLoopTimeoutDuration =
-            NN_TRY(utils::makeExecutionFailure(convertInput(loopTimeoutDuration)));
-
-    const auto [outputShapes, timing] =
-            NN_TRY(preparedModel->execute(nnRequest, nnMeasure, nnDeadline, nnLoopTimeoutDuration));
-
-    auto hidlOutputShapes = NN_TRY(utils::makeExecutionFailure(V1_3::utils::convert(outputShapes)));
-    const auto hidlTiming = NN_TRY(utils::makeExecutionFailure(V1_3::utils::convert(timing)));
-    return std::make_pair(std::move(hidlOutputShapes), hidlTiming);
-}
-
-nn::GeneralResult<std::vector<nn::SyncFence>> convertSyncFences(
-        const hidl_vec<hidl_handle>& handles) {
-    std::vector<nn::SyncFence> syncFences;
-    syncFences.reserve(handles.size());
-    for (const auto& handle : handles) {
-        auto nativeHandle = NN_TRY(convertInput(handle));
-        auto syncFence = NN_TRY(utils::makeGeneralFailure(
-                nn::SyncFence::create(std::move(nativeHandle)), nn::ErrorStatus::INVALID_ARGUMENT));
-        syncFences.push_back(std::move(syncFence));
-    }
-    return syncFences;
-}
-
-nn::GeneralResult<std::pair<hidl_handle, sp<V1_3::IFencedExecutionCallback>>> executeFenced(
-        const nn::SharedPreparedModel& preparedModel, const V1_3::Request& request,
-        const hidl_vec<hidl_handle>& waitFor, V1_2::MeasureTiming measure,
-        const V1_3::OptionalTimePoint& deadline,
-        const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
-        const V1_3::OptionalTimeoutDuration& duration) {
-    const auto nnRequest = NN_TRY(convertInput(request));
-    const auto nnWaitFor = NN_TRY(convertSyncFences(waitFor));
-    const auto nnMeasure = NN_TRY(convertInput(measure));
-    const auto nnDeadline = NN_TRY(convertInput(deadline));
-    const auto nnLoopTimeoutDuration = NN_TRY(convertInput(loopTimeoutDuration));
-    const auto nnDuration = NN_TRY(convertInput(duration));
-
-    auto [syncFence, executeFencedCallback] = NN_TRY(preparedModel->executeFenced(
-            nnRequest, nnWaitFor, nnMeasure, nnDeadline, nnLoopTimeoutDuration, nnDuration));
-
-    auto hidlSyncFence = NN_TRY(V1_3::utils::convert(syncFence.getSharedHandle()));
-    auto hidlExecuteFencedCallback = sp<FencedExecutionCallback>::make(executeFencedCallback);
-    return std::make_pair(std::move(hidlSyncFence), std::move(hidlExecuteFencedCallback));
-}
-
-}  // namespace
-
-PreparedModel::PreparedModel(nn::SharedPreparedModel preparedModel, Executor executor, uid_t userId)
-    : kPreparedModel(std::move(preparedModel)), kExecutor(std::move(executor)), kUserId(userId) {
-    CHECK(kPreparedModel != nullptr);
-    CHECK(kExecutor != nullptr);
-}
-
-nn::SharedPreparedModel PreparedModel::getUnderlyingPreparedModel() const {
-    return kPreparedModel;
-}
-
-Return<V1_0::ErrorStatus> PreparedModel::execute(const V1_0::Request& request,
-                                                 const sp<V1_0::IExecutionCallback>& callback) {
-    auto result = adapter::execute(kPreparedModel, kUserId, kExecutor, request, callback);
-    if (!result.has_value()) {
-        auto [message, code] = std::move(result).error();
-        LOG(ERROR) << "adapter::PreparedModel::execute failed with " << code << ": " << message;
-        notify(callback.get(), code, {}, {});
-        return V1_0::utils::convert(code).value();
-    }
-    return V1_0::ErrorStatus::NONE;
-}
-
-Return<V1_0::ErrorStatus> PreparedModel::execute_1_2(const V1_0::Request& request,
-                                                     V1_2::MeasureTiming measure,
-                                                     const sp<V1_2::IExecutionCallback>& callback) {
-    auto result =
-            adapter::execute_1_2(kPreparedModel, kUserId, kExecutor, request, measure, callback);
-    if (!result.has_value()) {
-        auto [message, code] = std::move(result).error();
-        LOG(ERROR) << "adapter::PreparedModel::execute_1_2 failed with " << code << ": " << message;
-        notify(callback.get(), code, {}, {});
-        return V1_2::utils::convert(code).value();
-    }
-    return V1_0::ErrorStatus::NONE;
-}
-
-Return<V1_3::ErrorStatus> PreparedModel::execute_1_3(
-        const V1_3::Request& request, V1_2::MeasureTiming measure,
-        const V1_3::OptionalTimePoint& deadline,
-        const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
-        const sp<V1_3::IExecutionCallback>& callback) {
-    auto result = adapter::execute_1_3(kPreparedModel, kUserId, kExecutor, request, measure,
-                                       deadline, loopTimeoutDuration, callback);
-    if (!result.has_value()) {
-        auto [message, code] = std::move(result).error();
-        LOG(ERROR) << "adapter::PreparedModel::execute_1_3 failed with " << code << ": " << message;
-        notify(callback.get(), code, {}, {});
-        return V1_3::utils::convert(code).value();
-    }
-    return V1_3::ErrorStatus::NONE;
-}
-
-Return<void> PreparedModel::executeSynchronously(const V1_0::Request& request,
-                                                 V1_2::MeasureTiming measure,
-                                                 executeSynchronously_cb cb) {
-    auto result = adapter::executeSynchronously(kPreparedModel, request, measure);
-    if (!result.has_value()) {
-        auto [message, code, outputShapes] = std::move(result).error();
-        LOG(ERROR) << "adapter::PreparedModel::executeSynchronously failed with " << code << ": "
-                   << message;
-        cb(V1_2::utils::convert(code).value(), V1_2::utils::convert(outputShapes).value(),
-           V1_2::utils::kNoTiming);
-        return Void();
-    }
-    auto [outputShapes, timing] = std::move(result).value();
-    cb(V1_0::ErrorStatus::NONE, outputShapes, timing);
-    return Void();
-}
-
-Return<void> PreparedModel::executeSynchronously_1_3(
-        const V1_3::Request& request, V1_2::MeasureTiming measure,
-        const V1_3::OptionalTimePoint& deadline,
-        const V1_3::OptionalTimeoutDuration& loopTimeoutDuration, executeSynchronously_1_3_cb cb) {
-    auto result = adapter::executeSynchronously_1_3(kPreparedModel, request, measure, deadline,
-                                                    loopTimeoutDuration);
-    if (!result.has_value()) {
-        auto [message, code, outputShapes] = std::move(result).error();
-        LOG(ERROR) << "adapter::PreparedModel::executeSynchronously_1_3 failed with " << code
-                   << ": " << message;
-        cb(V1_3::utils::convert(code).value(), V1_3::utils::convert(outputShapes).value(),
-           V1_2::utils::kNoTiming);
-        return Void();
-    }
-    auto [outputShapes, timing] = std::move(result).value();
-    cb(V1_3::ErrorStatus::NONE, outputShapes, timing);
-    return Void();
-}
-
-Return<void> PreparedModel::configureExecutionBurst(
-        const sp<V1_2::IBurstCallback>& callback,
-        const MQDescriptorSync<V1_2::FmqRequestDatum>& requestChannel,
-        const MQDescriptorSync<V1_2::FmqResultDatum>& resultChannel,
-        configureExecutionBurst_cb cb) {
-    const sp<V1_2::IBurstContext> burst = nn::ExecutionBurstServer::create(
-            callback, requestChannel, resultChannel, this, std::chrono::microseconds{0});
-
-    if (burst == nullptr) {
-        cb(V1_0::ErrorStatus::GENERAL_FAILURE, {});
-    } else {
-        cb(V1_0::ErrorStatus::NONE, burst);
-    }
-    return Void();
-}
-
-Return<void> PreparedModel::executeFenced(const V1_3::Request& request,
-                                          const hidl_vec<hidl_handle>& waitFor,
-                                          V1_2::MeasureTiming measure,
-                                          const V1_3::OptionalTimePoint& deadline,
-                                          const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
-                                          const V1_3::OptionalTimeoutDuration& duration,
-                                          executeFenced_cb callback) {
-    auto result = adapter::executeFenced(kPreparedModel, request, waitFor, measure, deadline,
-                                         loopTimeoutDuration, duration);
-    if (!result.has_value()) {
-        auto [message, code] = std::move(result).error();
-        LOG(ERROR) << "adapter::PreparedModel::executeFenced failed with " << code << ": "
-                   << message;
-        callback(V1_3::utils::convert(code).value(), {}, nullptr);
-        return Void();
-    }
-    auto [syncFence, executeFencedCallback] = std::move(result).value();
-    callback(V1_3::ErrorStatus::NONE, syncFence, executeFencedCallback);
-    return Void();
-}
-
-}  // namespace android::hardware::neuralnetworks::adapter
diff --git a/neuralnetworks/utils/common/Android.bp b/neuralnetworks/utils/common/Android.bp
index 20cd1f2..91fca2f 100644
--- a/neuralnetworks/utils/common/Android.bp
+++ b/neuralnetworks/utils/common/Android.bp
@@ -30,39 +30,27 @@
     local_include_dirs: ["include/nnapi/hal"],
     export_include_dirs: ["include"],
     cflags: ["-Wthread-safety"],
-    static_libs: [
-        "libarect",
-        "neuralnetworks_types",
-    ],
-    shared_libs: [
-        "android.hardware.neuralnetworks-V2-ndk_platform",
-        "libhidlbase",
-        "libnativewindow",
-        "libbinder_ndk",
-    ],
+    static_libs: ["neuralnetworks_types"],
 }
 
 cc_test {
     name: "neuralnetworks_utils_hal_common_test",
+    host_supported: true,
+    tidy_timeout_srcs: ["test/ResilientDeviceTest.cpp"],
     srcs: ["test/*.cpp"],
     static_libs: [
-        "android.hardware.neuralnetworks@1.0",
         "libgmock",
-        "libneuralnetworks_common",
         "neuralnetworks_types",
         "neuralnetworks_utils_hal_common",
     ],
     shared_libs: [
-        "android.hidl.allocator@1.0",
-        "android.hidl.memory@1.0",
         "libbase",
         "libcutils",
-        "libfmq",
-        "libhidlbase",
-        "libhidlmemory",
-        "liblog",
-        "libnativewindow",
-        "libutils",
     ],
+    target: {
+        android: {
+            shared_libs: ["libnativewindow"],
+        },
+    },
     test_suites: ["general-tests"],
 }
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/CommonUtils.h b/neuralnetworks/utils/common/include/nnapi/hal/CommonUtils.h
index 702ee92..c04294a 100644
--- a/neuralnetworks/utils/common/include/nnapi/hal/CommonUtils.h
+++ b/neuralnetworks/utils/common/include/nnapi/hal/CommonUtils.h
@@ -17,11 +17,10 @@
 #ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_COMMON_UTILS_H
 #define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_COMMON_UTILS_H
 
-#include <cutils/native_handle.h>
-#include <hidl/HidlSupport.h>
 #include <nnapi/Result.h>
 #include <nnapi/SharedMemory.h>
 #include <nnapi/Types.h>
+
 #include <functional>
 #include <vector>
 
@@ -49,93 +48,10 @@
         const nn::Capabilities::PerformanceInfo& float32Performance,
         const nn::Capabilities::PerformanceInfo& quantized8Performance);
 
-// Indicates if the object contains no pointer-based data that could be relocated to shared memory.
-bool hasNoPointerData(const nn::Model& model);
-bool hasNoPointerData(const nn::Request& request);
-
-// Relocate pointer-based data to shared memory. If `model` has no Operand::LifeTime::POINTER data,
-// the function returns with a reference to `model`. If `model` has Operand::LifeTime::POINTER data,
-// the model is copied to `maybeModelInSharedOut` with the POINTER data relocated to a memory pool,
-// and the function returns with a reference to `*maybeModelInSharedOut`.
-nn::GeneralResult<std::reference_wrapper<const nn::Model>> flushDataFromPointerToShared(
-        const nn::Model* model, std::optional<nn::Model>* maybeModelInSharedOut);
-
-// Record a relocation mapping between pointer-based data and shared memory.
-// Only two specializations of this template may exist:
-// - RelocationInfo<const void*> for request inputs
-// - RelocationInfo<void*> for request outputs
-template <typename PointerType>
-struct RelocationInfo {
-    PointerType data;
-    size_t length;
-    size_t offset;
-};
-using InputRelocationInfo = RelocationInfo<const void*>;
-using OutputRelocationInfo = RelocationInfo<void*>;
-
-// Keep track of the relocation mapping between pointer-based data and shared memory pool,
-// and provide method to copy the data between pointers and the shared memory pool.
-// Only two specializations of this template may exist:
-// - RelocationTracker<InputRelocationInfo> for request inputs
-// - RelocationTracker<OutputRelocationInfo> for request outputs
-template <typename RelocationInfoType>
-class RelocationTracker {
-  public:
-    static nn::GeneralResult<std::unique_ptr<RelocationTracker>> create(
-            std::vector<RelocationInfoType> relocationInfos, nn::SharedMemory memory) {
-        auto mapping = NN_TRY(map(memory));
-        return std::make_unique<RelocationTracker<RelocationInfoType>>(
-                std::move(relocationInfos), std::move(memory), std::move(mapping));
-    }
-
-    RelocationTracker(std::vector<RelocationInfoType> relocationInfos, nn::SharedMemory memory,
-                      nn::Mapping mapping)
-        : kRelocationInfos(std::move(relocationInfos)),
-          kMemory(std::move(memory)),
-          kMapping(std::move(mapping)) {}
-
-    // Specializations defined in CommonUtils.cpp.
-    // For InputRelocationTracker, this method will copy pointer data to the shared memory pool.
-    // For OutputRelocationTracker, this method will copy shared memory data to the pointers.
-    void flush() const;
-
-  private:
-    const std::vector<RelocationInfoType> kRelocationInfos;
-    const nn::SharedMemory kMemory;
-    const nn::Mapping kMapping;
-};
-using InputRelocationTracker = RelocationTracker<InputRelocationInfo>;
-using OutputRelocationTracker = RelocationTracker<OutputRelocationInfo>;
-
-struct RequestRelocation {
-    std::unique_ptr<InputRelocationTracker> input;
-    std::unique_ptr<OutputRelocationTracker> output;
-};
-
-// Relocate pointer-based data to shared memory. If `request` has no
-// Request::Argument::LifeTime::POINTER data, the function returns with a reference to `request`. If
-// `request` has Request::Argument::LifeTime::POINTER data, the request is copied to
-// `maybeRequestInSharedOut` with the POINTER data relocated to a memory pool, and the function
-// returns with a reference to `*maybeRequestInSharedOut`. The `relocationOut` will be set to track
-// the input and output relocations.
-//
-// Unlike `flushDataFromPointerToShared`, this method will not copy the input pointer data to the
-// shared memory pool. Use `relocationOut` to flush the input or output data after the call.
-nn::GeneralResult<std::reference_wrapper<const nn::Request>> convertRequestFromPointerToShared(
-        const nn::Request* request, uint32_t alignment, uint32_t padding,
-        std::optional<nn::Request>* maybeRequestInSharedOut, RequestRelocation* relocationOut);
-
-nn::GeneralResult<std::vector<uint32_t>> countNumberOfConsumers(
-        size_t numberOfOperands, const std::vector<nn::Operation>& operations);
-
-nn::GeneralResult<hidl_memory> createHidlMemoryFromSharedMemory(const nn::SharedMemory& memory);
-nn::GeneralResult<nn::SharedMemory> createSharedMemoryFromHidlMemory(const hidl_memory& memory);
-
-nn::GeneralResult<hidl_handle> hidlHandleFromSharedHandle(const nn::Handle& handle);
-nn::GeneralResult<nn::Handle> sharedHandleFromNativeHandle(const native_handle_t* handle);
-
-nn::GeneralResult<hidl_vec<hidl_handle>> convertSyncFences(
-        const std::vector<nn::SyncFence>& fences);
+using nn::convertRequestFromPointerToShared;
+using nn::flushDataFromPointerToShared;
+using nn::hasNoPointerData;
+using nn::RequestRelocation;
 
 }  // namespace android::hardware::neuralnetworks::utils
 
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/HandleError.h b/neuralnetworks/utils/common/include/nnapi/hal/HandleError.h
deleted file mode 100644
index 209b663..0000000
--- a/neuralnetworks/utils/common/include/nnapi/hal/HandleError.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_HANDLE_ERROR_H
-#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_HANDLE_ERROR_H
-
-#include <android/hidl/base/1.0/IBase.h>
-#include <hidl/HidlSupport.h>
-#include <nnapi/Result.h>
-#include <nnapi/Types.h>
-
-#include <type_traits>
-
-namespace android::hardware::neuralnetworks::utils {
-
-template <typename Type>
-nn::GeneralResult<Type> handleTransportError(const hardware::Return<Type>& ret) {
-    if (ret.isDeadObject()) {
-        return nn::error(nn::ErrorStatus::DEAD_OBJECT)
-               << "Return<>::isDeadObject returned true: " << ret.description();
-    }
-    if (!ret.isOk()) {
-        return nn::error(nn::ErrorStatus::GENERAL_FAILURE)
-               << "Return<>::isOk returned false: " << ret.description();
-    }
-    if constexpr (!std::is_same_v<Type, void>) {
-        return static_cast<Type>(ret);
-    } else {
-        return {};
-    }
-}
-
-#define HANDLE_TRANSPORT_FAILURE(ret)                                                        \
-    ({                                                                                       \
-        auto result = ::android::hardware::neuralnetworks::utils::handleTransportError(ret); \
-        if (!result.has_value()) {                                                           \
-            return NN_ERROR(result.error().code) << result.error().message;                  \
-        }                                                                                    \
-        std::move(result).value();                                                           \
-    })
-
-template <typename Type>
-nn::GeneralResult<Type> makeGeneralFailure(
-        nn::Result<Type> result, nn::ErrorStatus status = nn::ErrorStatus::GENERAL_FAILURE) {
-    if (!result.has_value()) {
-        return nn::error(status) << std::move(result).error();
-    }
-    if constexpr (!std::is_same_v<Type, void>) {
-        return std::move(result).value();
-    } else {
-        return {};
-    }
-}
-
-template <typename Type>
-nn::ExecutionResult<Type> makeExecutionFailure(nn::GeneralResult<Type> result) {
-    if (!result.has_value()) {
-        const auto [message, status] = std::move(result).error();
-        return nn::error(status) << message;
-    }
-    if constexpr (!std::is_same_v<Type, void>) {
-        return std::move(result).value();
-    } else {
-        return {};
-    }
-}
-
-template <typename Type>
-nn::ExecutionResult<Type> makeExecutionFailure(
-        nn::Result<Type> result, nn::ErrorStatus status = nn::ErrorStatus::GENERAL_FAILURE) {
-    return makeExecutionFailure(makeGeneralFailure(result, status));
-}
-
-#define HANDLE_HAL_STATUS(status)                                       \
-    if (const auto canonical = ::android::nn::convert(status).value_or( \
-                ::android::nn::ErrorStatus::GENERAL_FAILURE);           \
-        canonical == ::android::nn::ErrorStatus::NONE) {                \
-    } else                                                              \
-        return NN_ERROR(canonical)
-
-}  // namespace android::hardware::neuralnetworks::utils
-
-#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_HANDLE_ERROR_H
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/InvalidBurst.h b/neuralnetworks/utils/common/include/nnapi/hal/InvalidBurst.h
index e86edda..1f1245f 100644
--- a/neuralnetworks/utils/common/include/nnapi/hal/InvalidBurst.h
+++ b/neuralnetworks/utils/common/include/nnapi/hal/InvalidBurst.h
@@ -33,12 +33,15 @@
 
     nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
             const nn::Request& request, nn::MeasureTiming measure,
-            const nn::OptionalTimePoint& deadline,
-            const nn::OptionalDuration& loopTimeoutDuration) const override;
+            const nn::OptionalTimePoint& deadline, const nn::OptionalDuration& loopTimeoutDuration,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
 
     nn::GeneralResult<nn::SharedExecution> createReusableExecution(
             const nn::Request& request, nn::MeasureTiming measure,
-            const nn::OptionalDuration& loopTimeoutDuration) const override;
+            const nn::OptionalDuration& loopTimeoutDuration,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
 };
 
 }  // namespace android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/InvalidDevice.h b/neuralnetworks/utils/common/include/nnapi/hal/InvalidDevice.h
index 5e62b9a..9582873 100644
--- a/neuralnetworks/utils/common/include/nnapi/hal/InvalidDevice.h
+++ b/neuralnetworks/utils/common/include/nnapi/hal/InvalidDevice.h
@@ -52,8 +52,9 @@
     nn::GeneralResult<nn::SharedPreparedModel> prepareModel(
             const nn::Model& model, nn::ExecutionPreference preference, nn::Priority priority,
             nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
-            const std::vector<nn::SharedHandle>& dataCache,
-            const nn::CacheToken& token) const override;
+            const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
 
     nn::GeneralResult<nn::SharedPreparedModel> prepareModelFromCache(
             nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/InvalidPreparedModel.h b/neuralnetworks/utils/common/include/nnapi/hal/InvalidPreparedModel.h
index de30aae..3f1f290 100644
--- a/neuralnetworks/utils/common/include/nnapi/hal/InvalidPreparedModel.h
+++ b/neuralnetworks/utils/common/include/nnapi/hal/InvalidPreparedModel.h
@@ -31,18 +31,23 @@
   public:
     nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
             const nn::Request& request, nn::MeasureTiming measure,
-            const nn::OptionalTimePoint& deadline,
-            const nn::OptionalDuration& loopTimeoutDuration) const override;
+            const nn::OptionalTimePoint& deadline, const nn::OptionalDuration& loopTimeoutDuration,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
 
     nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>> executeFenced(
             const nn::Request& request, const std::vector<nn::SyncFence>& waitFor,
             nn::MeasureTiming measure, const nn::OptionalTimePoint& deadline,
             const nn::OptionalDuration& loopTimeoutDuration,
-            const nn::OptionalDuration& timeoutDurationAfterFence) const override;
+            const nn::OptionalDuration& timeoutDurationAfterFence,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
 
     nn::GeneralResult<nn::SharedExecution> createReusableExecution(
             const nn::Request& request, nn::MeasureTiming measure,
-            const nn::OptionalDuration& loopTimeoutDuration) const override;
+            const nn::OptionalDuration& loopTimeoutDuration,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
 
     nn::GeneralResult<nn::SharedBurst> configureExecutionBurst() const override;
 
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/ProtectCallback.h b/neuralnetworks/utils/common/include/nnapi/hal/ProtectCallback.h
deleted file mode 100644
index 05110bc..0000000
--- a/neuralnetworks/utils/common/include/nnapi/hal/ProtectCallback.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_PROTECT_CALLBACK_H
-#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_PROTECT_CALLBACK_H
-
-#include <android-base/scopeguard.h>
-#include <android-base/thread_annotations.h>
-#include <android/hidl/base/1.0/IBase.h>
-#include <hidl/HidlSupport.h>
-#include <nnapi/Result.h>
-#include <nnapi/Types.h>
-
-#include <functional>
-#include <mutex>
-#include <vector>
-
-// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
-// lifetimes across processes and for protecting asynchronous calls across HIDL.
-
-namespace android::hardware::neuralnetworks::utils {
-
-class IProtectedCallback {
-  public:
-    /**
-     * Marks this object as a dead object.
-     */
-    virtual void notifyAsDeadObject() = 0;
-
-    // Public virtual destructor to allow objects to be stored (and destroyed) as smart pointers.
-    // E.g., std::unique_ptr<IProtectedCallback>.
-    virtual ~IProtectedCallback() = default;
-
-  protected:
-    // Protect the non-destructor special member functions to prevent object slicing.
-    IProtectedCallback() = default;
-    IProtectedCallback(const IProtectedCallback&) = default;
-    IProtectedCallback(IProtectedCallback&&) noexcept = default;
-    IProtectedCallback& operator=(const IProtectedCallback&) = default;
-    IProtectedCallback& operator=(IProtectedCallback&&) noexcept = default;
-};
-
-// Thread safe class
-class DeathRecipient final : public hidl_death_recipient {
-  public:
-    void serviceDied(uint64_t cookie, const wp<hidl::base::V1_0::IBase>& who) override;
-    // Precondition: `killable` must be non-null.
-    void add(IProtectedCallback* killable) const;
-    // Precondition: `killable` must be non-null.
-    void remove(IProtectedCallback* killable) const;
-
-  private:
-    mutable std::mutex mMutex;
-    mutable bool mIsDeadObject GUARDED_BY(mMutex) = false;
-    mutable std::vector<IProtectedCallback*> mObjects GUARDED_BY(mMutex);
-};
-
-class DeathHandler final {
-  public:
-    static nn::GeneralResult<DeathHandler> create(sp<hidl::base::V1_0::IBase> object);
-
-    DeathHandler(const DeathHandler&) = delete;
-    DeathHandler(DeathHandler&&) noexcept = default;
-    DeathHandler& operator=(const DeathHandler&) = delete;
-    DeathHandler& operator=(DeathHandler&&) noexcept = delete;
-    ~DeathHandler();
-
-    using Cleanup = std::function<void()>;
-    using Hold = base::ScopeGuard<Cleanup>;
-
-    // Precondition: `killable` must be non-null.
-    // `killable` must outlive the return value `Hold`.
-    [[nodiscard]] Hold protectCallback(IProtectedCallback* killable) const;
-
-    // Precondition: `killable` must be non-null.
-    // `killable` must outlive the `DeathHandler`.
-    void protectCallbackForLifetimeOfDeathHandler(IProtectedCallback* killable) const;
-
-  private:
-    DeathHandler(sp<hidl::base::V1_0::IBase> object, sp<DeathRecipient> deathRecipient);
-
-    sp<hidl::base::V1_0::IBase> mObject;
-    sp<DeathRecipient> mDeathRecipient;
-};
-
-}  // namespace android::hardware::neuralnetworks::utils
-
-#endif  // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_PROTECT_CALLBACK_H
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/ResilientBurst.h b/neuralnetworks/utils/common/include/nnapi/hal/ResilientBurst.h
index fde2486..129431f 100644
--- a/neuralnetworks/utils/common/include/nnapi/hal/ResilientBurst.h
+++ b/neuralnetworks/utils/common/include/nnapi/hal/ResilientBurst.h
@@ -48,18 +48,23 @@
 
     nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
             const nn::Request& request, nn::MeasureTiming measure,
-            const nn::OptionalTimePoint& deadline,
-            const nn::OptionalDuration& loopTimeoutDuration) const override;
+            const nn::OptionalTimePoint& deadline, const nn::OptionalDuration& loopTimeoutDuration,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
 
     nn::GeneralResult<nn::SharedExecution> createReusableExecution(
             const nn::Request& request, nn::MeasureTiming measure,
-            const nn::OptionalDuration& loopTimeoutDuration) const override;
+            const nn::OptionalDuration& loopTimeoutDuration,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
 
   private:
     bool isValidInternal() const EXCLUDES(mMutex);
     nn::GeneralResult<nn::SharedExecution> createReusableExecutionInternal(
             const nn::Request& request, nn::MeasureTiming measure,
-            const nn::OptionalDuration& loopTimeoutDuration) const;
+            const nn::OptionalDuration& loopTimeoutDuration,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const;
 
     const Factory kMakeBurst;
     mutable std::mutex mMutex;
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/ResilientDevice.h b/neuralnetworks/utils/common/include/nnapi/hal/ResilientDevice.h
index 84ae799..267d634 100644
--- a/neuralnetworks/utils/common/include/nnapi/hal/ResilientDevice.h
+++ b/neuralnetworks/utils/common/include/nnapi/hal/ResilientDevice.h
@@ -65,8 +65,9 @@
     nn::GeneralResult<nn::SharedPreparedModel> prepareModel(
             const nn::Model& model, nn::ExecutionPreference preference, nn::Priority priority,
             nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
-            const std::vector<nn::SharedHandle>& dataCache,
-            const nn::CacheToken& token) const override;
+            const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
 
     nn::GeneralResult<nn::SharedPreparedModel> prepareModelFromCache(
             nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
@@ -83,7 +84,9 @@
     nn::GeneralResult<nn::SharedPreparedModel> prepareModelInternal(
             const nn::Model& model, nn::ExecutionPreference preference, nn::Priority priority,
             nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
-            const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token) const;
+            const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const;
     nn::GeneralResult<nn::SharedPreparedModel> prepareModelFromCacheInternal(
             nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
             const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token) const;
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/ResilientPreparedModel.h b/neuralnetworks/utils/common/include/nnapi/hal/ResilientPreparedModel.h
index 86533ed..bbfc220 100644
--- a/neuralnetworks/utils/common/include/nnapi/hal/ResilientPreparedModel.h
+++ b/neuralnetworks/utils/common/include/nnapi/hal/ResilientPreparedModel.h
@@ -49,18 +49,23 @@
 
     nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
             const nn::Request& request, nn::MeasureTiming measure,
-            const nn::OptionalTimePoint& deadline,
-            const nn::OptionalDuration& loopTimeoutDuration) const override;
+            const nn::OptionalTimePoint& deadline, const nn::OptionalDuration& loopTimeoutDuration,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
 
     nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>> executeFenced(
             const nn::Request& request, const std::vector<nn::SyncFence>& waitFor,
             nn::MeasureTiming measure, const nn::OptionalTimePoint& deadline,
             const nn::OptionalDuration& loopTimeoutDuration,
-            const nn::OptionalDuration& timeoutDurationAfterFence) const override;
+            const nn::OptionalDuration& timeoutDurationAfterFence,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
 
     nn::GeneralResult<nn::SharedExecution> createReusableExecution(
             const nn::Request& request, nn::MeasureTiming measure,
-            const nn::OptionalDuration& loopTimeoutDuration) const override;
+            const nn::OptionalDuration& loopTimeoutDuration,
+            const std::vector<nn::TokenValuePair>& hints,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const override;
 
     nn::GeneralResult<nn::SharedBurst> configureExecutionBurst() const override;
 
@@ -70,7 +75,9 @@
     bool isValidInternal() const EXCLUDES(mMutex);
     nn::GeneralResult<nn::SharedExecution> createReusableExecutionInternal(
             const nn::Request& request, nn::MeasureTiming measure,
-            const nn::OptionalDuration& loopTimeoutDuration) const;
+            const nn::OptionalDuration& loopTimeoutDuration,
+            const std::vector<nn::TokenValuePair>& metaData,
+            const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const;
     nn::GeneralResult<nn::SharedBurst> configureExecutionBurstInternal() const;
 
     const Factory kMakePreparedModel;
diff --git a/neuralnetworks/utils/common/src/CommonUtils.cpp b/neuralnetworks/utils/common/src/CommonUtils.cpp
index 8e55bf0..dd55add 100644
--- a/neuralnetworks/utils/common/src/CommonUtils.cpp
+++ b/neuralnetworks/utils/common/src/CommonUtils.cpp
@@ -16,18 +16,12 @@
 
 #include "CommonUtils.h"
 
-#include "HandleError.h"
-
 #include <android-base/logging.h>
-#include <android-base/unique_fd.h>
-#include <android/hardware_buffer.h>
-#include <hidl/HidlSupport.h>
 #include <nnapi/Result.h>
 #include <nnapi/SharedMemory.h>
 #include <nnapi/TypeUtils.h>
 #include <nnapi/Types.h>
 #include <nnapi/Validation.h>
-#include <vndk/hardware_buffer.h>
 
 #include <algorithm>
 #include <any>
@@ -37,112 +31,6 @@
 #include <vector>
 
 namespace android::hardware::neuralnetworks::utils {
-namespace {
-
-bool hasNoPointerData(const nn::Operand& operand);
-bool hasNoPointerData(const nn::Model::Subgraph& subgraph);
-bool hasNoPointerData(const nn::Request::Argument& argument);
-
-template <typename Type>
-bool hasNoPointerData(const std::vector<Type>& objects) {
-    return std::all_of(objects.begin(), objects.end(),
-                       [](const auto& object) { return hasNoPointerData(object); });
-}
-
-bool hasNoPointerData(const nn::DataLocation& location) {
-    return std::visit([](auto ptr) { return ptr == nullptr; }, location.pointer);
-}
-
-bool hasNoPointerData(const nn::Operand& operand) {
-    return hasNoPointerData(operand.location);
-}
-
-bool hasNoPointerData(const nn::Model::Subgraph& subgraph) {
-    return hasNoPointerData(subgraph.operands);
-}
-
-bool hasNoPointerData(const nn::Request::Argument& argument) {
-    return hasNoPointerData(argument.location);
-}
-
-void copyPointersToSharedMemory(nn::Operand* operand, nn::ConstantMemoryBuilder* memoryBuilder) {
-    CHECK(operand != nullptr);
-    CHECK(memoryBuilder != nullptr);
-
-    if (operand->lifetime != nn::Operand::LifeTime::POINTER) {
-        return;
-    }
-
-    const void* data = std::visit([](auto ptr) { return static_cast<const void*>(ptr); },
-                                  operand->location.pointer);
-    CHECK(data != nullptr);
-    operand->lifetime = nn::Operand::LifeTime::CONSTANT_REFERENCE;
-    operand->location = memoryBuilder->append(data, operand->location.length);
-}
-
-void copyPointersToSharedMemory(nn::Model::Subgraph* subgraph,
-                                nn::ConstantMemoryBuilder* memoryBuilder) {
-    CHECK(subgraph != nullptr);
-    std::for_each(subgraph->operands.begin(), subgraph->operands.end(),
-                  [memoryBuilder](auto& operand) {
-                      copyPointersToSharedMemory(&operand, memoryBuilder);
-                  });
-}
-
-nn::GeneralResult<hidl_handle> createNativeHandleFrom(base::unique_fd fd,
-                                                      const std::vector<int32_t>& ints) {
-    constexpr size_t kIntMax = std::numeric_limits<int>::max();
-    CHECK_LE(ints.size(), kIntMax);
-    native_handle_t* nativeHandle = native_handle_create(1, static_cast<int>(ints.size()));
-    if (nativeHandle == nullptr) {
-        return NN_ERROR() << "Failed to create native_handle";
-    }
-
-    nativeHandle->data[0] = fd.release();
-    std::copy(ints.begin(), ints.end(), nativeHandle->data + 1);
-
-    hidl_handle handle;
-    handle.setTo(nativeHandle, /*shouldOwn=*/true);
-    return handle;
-}
-
-nn::GeneralResult<hidl_memory> createHidlMemoryFrom(const nn::Memory::Ashmem& memory) {
-    auto fd = NN_TRY(nn::dupFd(memory.fd));
-    auto handle = NN_TRY(createNativeHandleFrom(std::move(fd), {}));
-    return hidl_memory("ashmem", std::move(handle), memory.size);
-}
-
-nn::GeneralResult<hidl_memory> createHidlMemoryFrom(const nn::Memory::Fd& memory) {
-    auto fd = NN_TRY(nn::dupFd(memory.fd));
-
-    const auto [lowOffsetBits, highOffsetBits] = nn::getIntsFromOffset(memory.offset);
-    const std::vector<int> ints = {memory.prot, lowOffsetBits, highOffsetBits};
-
-    auto handle = NN_TRY(createNativeHandleFrom(std::move(fd), ints));
-    return hidl_memory("mmap_fd", std::move(handle), memory.size);
-}
-
-nn::GeneralResult<hidl_memory> createHidlMemoryFrom(const nn::Memory::HardwareBuffer& memory) {
-    const auto* ahwb = memory.handle.get();
-    AHardwareBuffer_Desc bufferDesc;
-    AHardwareBuffer_describe(ahwb, &bufferDesc);
-
-    const bool isBlob = bufferDesc.format == AHARDWAREBUFFER_FORMAT_BLOB;
-    const size_t size = isBlob ? bufferDesc.width : 0;
-    const char* const name = isBlob ? "hardware_buffer_blob" : "hardware_buffer";
-
-    const native_handle_t* nativeHandle = AHardwareBuffer_getNativeHandle(ahwb);
-    const hidl_handle hidlHandle(nativeHandle);
-    hidl_handle copiedHandle(hidlHandle);
-
-    return hidl_memory(name, std::move(copiedHandle), size);
-}
-
-nn::GeneralResult<hidl_memory> createHidlMemoryFrom(const nn::Memory::Unknown& memory) {
-    return hidl_memory(memory.name, NN_TRY(hidlHandleFromSharedHandle(memory.handle)), memory.size);
-}
-
-}  // anonymous namespace
 
 nn::Capabilities::OperandPerformanceTable makeQuantized8PerformanceConsistentWithP(
         const nn::Capabilities::PerformanceInfo& float32Performance,
@@ -163,298 +51,4 @@
             .value();
 }
 
-bool hasNoPointerData(const nn::Model& model) {
-    return hasNoPointerData(model.main) && hasNoPointerData(model.referenced);
-}
-
-bool hasNoPointerData(const nn::Request& request) {
-    return hasNoPointerData(request.inputs) && hasNoPointerData(request.outputs);
-}
-
-nn::GeneralResult<std::reference_wrapper<const nn::Model>> flushDataFromPointerToShared(
-        const nn::Model* model, std::optional<nn::Model>* maybeModelInSharedOut) {
-    CHECK(model != nullptr);
-    CHECK(maybeModelInSharedOut != nullptr);
-
-    if (hasNoPointerData(*model)) {
-        return *model;
-    }
-
-    // Make a copy of the model in order to make modifications. The modified model is returned to
-    // the caller through `maybeModelInSharedOut` if the function succeeds.
-    nn::Model modelInShared = *model;
-
-    nn::ConstantMemoryBuilder memoryBuilder(modelInShared.pools.size());
-    copyPointersToSharedMemory(&modelInShared.main, &memoryBuilder);
-    std::for_each(modelInShared.referenced.begin(), modelInShared.referenced.end(),
-                  [&memoryBuilder](auto& subgraph) {
-                      copyPointersToSharedMemory(&subgraph, &memoryBuilder);
-                  });
-
-    if (!memoryBuilder.empty()) {
-        auto memory = NN_TRY(memoryBuilder.finish());
-        modelInShared.pools.push_back(std::move(memory));
-    }
-
-    *maybeModelInSharedOut = modelInShared;
-    return **maybeModelInSharedOut;
-}
-
-template <>
-void InputRelocationTracker::flush() const {
-    // Copy from pointers to shared memory.
-    uint8_t* memoryPtr = static_cast<uint8_t*>(std::get<void*>(kMapping.pointer));
-    for (const auto& [data, length, offset] : kRelocationInfos) {
-        std::memcpy(memoryPtr + offset, data, length);
-    }
-}
-
-template <>
-void OutputRelocationTracker::flush() const {
-    // Copy from shared memory to pointers.
-    const uint8_t* memoryPtr = static_cast<const uint8_t*>(
-            std::visit([](auto ptr) { return static_cast<const void*>(ptr); }, kMapping.pointer));
-    for (const auto& [data, length, offset] : kRelocationInfos) {
-        std::memcpy(data, memoryPtr + offset, length);
-    }
-}
-
-nn::GeneralResult<std::reference_wrapper<const nn::Request>> convertRequestFromPointerToShared(
-        const nn::Request* request, uint32_t alignment, uint32_t padding,
-        std::optional<nn::Request>* maybeRequestInSharedOut, RequestRelocation* relocationOut) {
-    CHECK(request != nullptr);
-    CHECK(maybeRequestInSharedOut != nullptr);
-    CHECK(relocationOut != nullptr);
-
-    if (hasNoPointerData(*request)) {
-        return *request;
-    }
-
-    // Make a copy of the request in order to make modifications. The modified request is returned
-    // to the caller through `maybeRequestInSharedOut` if the function succeeds.
-    nn::Request requestInShared = *request;
-
-    RequestRelocation relocation;
-
-    // Change input pointers to shared memory.
-    nn::MutableMemoryBuilder inputBuilder(requestInShared.pools.size());
-    std::vector<InputRelocationInfo> inputRelocationInfos;
-    for (auto& input : requestInShared.inputs) {
-        const auto& location = input.location;
-        if (input.lifetime != nn::Request::Argument::LifeTime::POINTER) {
-            continue;
-        }
-
-        input.lifetime = nn::Request::Argument::LifeTime::POOL;
-        const void* data = std::visit([](auto ptr) { return static_cast<const void*>(ptr); },
-                                      location.pointer);
-        CHECK(data != nullptr);
-        input.location = inputBuilder.append(location.length, alignment, padding);
-        inputRelocationInfos.push_back({data, input.location.length, input.location.offset});
-    }
-
-    // Allocate input memory.
-    if (!inputBuilder.empty()) {
-        auto memory = NN_TRY(inputBuilder.finish());
-        requestInShared.pools.push_back(memory);
-        relocation.input = NN_TRY(
-                InputRelocationTracker::create(std::move(inputRelocationInfos), std::move(memory)));
-    }
-
-    // Change output pointers to shared memory.
-    nn::MutableMemoryBuilder outputBuilder(requestInShared.pools.size());
-    std::vector<OutputRelocationInfo> outputRelocationInfos;
-    for (auto& output : requestInShared.outputs) {
-        const auto& location = output.location;
-        if (output.lifetime != nn::Request::Argument::LifeTime::POINTER) {
-            continue;
-        }
-
-        output.lifetime = nn::Request::Argument::LifeTime::POOL;
-        void* data = std::get<void*>(location.pointer);
-        CHECK(data != nullptr);
-        output.location = outputBuilder.append(location.length, alignment, padding);
-        outputRelocationInfos.push_back({data, output.location.length, output.location.offset});
-    }
-
-    // Allocate output memory.
-    if (!outputBuilder.empty()) {
-        auto memory = NN_TRY(outputBuilder.finish());
-        requestInShared.pools.push_back(memory);
-        relocation.output = NN_TRY(OutputRelocationTracker::create(std::move(outputRelocationInfos),
-                                                                   std::move(memory)));
-    }
-
-    *maybeRequestInSharedOut = requestInShared;
-    *relocationOut = std::move(relocation);
-    return **maybeRequestInSharedOut;
-}
-
-nn::GeneralResult<std::vector<uint32_t>> countNumberOfConsumers(
-        size_t numberOfOperands, const std::vector<nn::Operation>& operations) {
-    return makeGeneralFailure(nn::countNumberOfConsumers(numberOfOperands, operations));
-}
-
-nn::GeneralResult<hidl_memory> createHidlMemoryFromSharedMemory(const nn::SharedMemory& memory) {
-    if (memory == nullptr) {
-        return NN_ERROR() << "Memory must be non-empty";
-    }
-    return std::visit([](const auto& x) { return createHidlMemoryFrom(x); }, memory->handle);
-}
-
-static uint32_t roundUpToMultiple(uint32_t value, uint32_t multiple) {
-    return (value + multiple - 1) / multiple * multiple;
-}
-
-nn::GeneralResult<nn::SharedMemory> createSharedMemoryFromHidlMemory(const hidl_memory& memory) {
-    CHECK_LE(memory.size(), std::numeric_limits<size_t>::max());
-    if (!memory.valid()) {
-        return NN_ERROR() << "Unable to convert invalid hidl_memory";
-    }
-
-    if (memory.name() == "ashmem") {
-        if (memory.handle()->numFds != 1) {
-            return NN_ERROR() << "Unable to convert invalid ashmem memory object with "
-                              << memory.handle()->numFds << " numFds, but expected 1";
-        }
-        if (memory.handle()->numInts != 0) {
-            return NN_ERROR() << "Unable to convert invalid ashmem memory object with "
-                              << memory.handle()->numInts << " numInts, but expected 0";
-        }
-        auto handle = nn::Memory::Ashmem{
-                .fd = NN_TRY(nn::dupFd(memory.handle()->data[0])),
-                .size = static_cast<size_t>(memory.size()),
-        };
-        return std::make_shared<const nn::Memory>(nn::Memory{.handle = std::move(handle)});
-    }
-
-    if (memory.name() == "mmap_fd") {
-        if (memory.handle()->numFds != 1) {
-            return NN_ERROR() << "Unable to convert invalid mmap_fd memory object with "
-                              << memory.handle()->numFds << " numFds, but expected 1";
-        }
-        if (memory.handle()->numInts != 3) {
-            return NN_ERROR() << "Unable to convert invalid mmap_fd memory object with "
-                              << memory.handle()->numInts << " numInts, but expected 3";
-        }
-
-        const int fd = memory.handle()->data[0];
-        const int prot = memory.handle()->data[1];
-        const int lower = memory.handle()->data[2];
-        const int higher = memory.handle()->data[3];
-        const size_t offset = nn::getOffsetFromInts(lower, higher);
-
-        return nn::createSharedMemoryFromFd(static_cast<size_t>(memory.size()), prot, fd, offset);
-    }
-
-    if (memory.name() != "hardware_buffer_blob") {
-        auto handle = nn::Memory::Unknown{
-                .handle = NN_TRY(sharedHandleFromNativeHandle(memory.handle())),
-                .size = static_cast<size_t>(memory.size()),
-                .name = memory.name(),
-        };
-        return std::make_shared<const nn::Memory>(nn::Memory{.handle = std::move(handle)});
-    }
-
-    const auto size = memory.size();
-    const auto format = AHARDWAREBUFFER_FORMAT_BLOB;
-    const auto usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
-    const uint32_t width = size;
-    const uint32_t height = 1;  // height is always 1 for BLOB mode AHardwareBuffer.
-    const uint32_t layers = 1;  // layers is always 1 for BLOB mode AHardwareBuffer.
-
-    // AHardwareBuffer_createFromHandle() might fail because an allocator
-    // expects a specific stride value. In that case, we try to guess it by
-    // aligning the width to small powers of 2.
-    // TODO(b/174120849): Avoid stride assumptions.
-    AHardwareBuffer* hardwareBuffer = nullptr;
-    status_t status = UNKNOWN_ERROR;
-    for (uint32_t alignment : {1, 4, 32, 64, 128, 2, 8, 16}) {
-        const uint32_t stride = roundUpToMultiple(width, alignment);
-        AHardwareBuffer_Desc desc{
-                .width = width,
-                .height = height,
-                .layers = layers,
-                .format = format,
-                .usage = usage,
-                .stride = stride,
-        };
-        status = AHardwareBuffer_createFromHandle(&desc, memory.handle(),
-                                                  AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_CLONE,
-                                                  &hardwareBuffer);
-        if (status == NO_ERROR) {
-            break;
-        }
-    }
-    if (status != NO_ERROR) {
-        return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
-               << "Can't create AHardwareBuffer from handle. Error: " << status;
-    }
-
-    return nn::createSharedMemoryFromAHWB(hardwareBuffer, /*takeOwnership=*/true);
-}
-
-nn::GeneralResult<hidl_handle> hidlHandleFromSharedHandle(const nn::Handle& handle) {
-    std::vector<base::unique_fd> fds;
-    fds.reserve(handle.fds.size());
-    for (const auto& fd : handle.fds) {
-        const int dupFd = dup(fd);
-        if (dupFd == -1) {
-            return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "Failed to dup the fd";
-        }
-        fds.emplace_back(dupFd);
-    }
-
-    constexpr size_t kIntMax = std::numeric_limits<int>::max();
-    CHECK_LE(handle.fds.size(), kIntMax);
-    CHECK_LE(handle.ints.size(), kIntMax);
-    native_handle_t* nativeHandle = native_handle_create(static_cast<int>(handle.fds.size()),
-                                                         static_cast<int>(handle.ints.size()));
-    if (nativeHandle == nullptr) {
-        return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "Failed to create native_handle";
-    }
-    for (size_t i = 0; i < fds.size(); ++i) {
-        nativeHandle->data[i] = fds[i].release();
-    }
-    std::copy(handle.ints.begin(), handle.ints.end(), &nativeHandle->data[nativeHandle->numFds]);
-
-    hidl_handle hidlHandle;
-    hidlHandle.setTo(nativeHandle, /*shouldOwn=*/true);
-    return hidlHandle;
-}
-
-nn::GeneralResult<nn::Handle> sharedHandleFromNativeHandle(const native_handle_t* handle) {
-    if (handle == nullptr) {
-        return NN_ERROR() << "sharedHandleFromNativeHandle failed because handle is nullptr";
-    }
-
-    std::vector<base::unique_fd> fds;
-    fds.reserve(handle->numFds);
-    for (int i = 0; i < handle->numFds; ++i) {
-        const int dupFd = dup(handle->data[i]);
-        if (dupFd == -1) {
-            return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "Failed to dup the fd";
-        }
-        fds.emplace_back(dupFd);
-    }
-
-    std::vector<int> ints(&handle->data[handle->numFds],
-                          &handle->data[handle->numFds + handle->numInts]);
-
-    return nn::Handle{.fds = std::move(fds), .ints = std::move(ints)};
-}
-
-nn::GeneralResult<hidl_vec<hidl_handle>> convertSyncFences(
-        const std::vector<nn::SyncFence>& syncFences) {
-    hidl_vec<hidl_handle> handles(syncFences.size());
-    for (size_t i = 0; i < syncFences.size(); ++i) {
-        const auto& handle = syncFences[i].getSharedHandle();
-        if (handle == nullptr) {
-            return NN_ERROR() << "convertSyncFences failed because sync fence is empty";
-        }
-        handles[i] = NN_TRY(hidlHandleFromSharedHandle(*handle));
-    }
-    return handles;
-}
-
 }  // namespace android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/utils/common/src/InvalidBurst.cpp b/neuralnetworks/utils/common/src/InvalidBurst.cpp
index 0191533..3fdfb5c 100644
--- a/neuralnetworks/utils/common/src/InvalidBurst.cpp
+++ b/neuralnetworks/utils/common/src/InvalidBurst.cpp
@@ -34,13 +34,17 @@
 nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> InvalidBurst::execute(
         const nn::Request& /*request*/, nn::MeasureTiming /*measure*/,
         const nn::OptionalTimePoint& /*deadline*/,
-        const nn::OptionalDuration& /*loopTimeoutDuration*/) const {
+        const nn::OptionalDuration& /*loopTimeoutDuration*/,
+        const std::vector<nn::TokenValuePair>& /*hints*/,
+        const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
     return NN_ERROR() << "InvalidBurst";
 }
 
 nn::GeneralResult<nn::SharedExecution> InvalidBurst::createReusableExecution(
         const nn::Request& /*request*/, nn::MeasureTiming /*measure*/,
-        const nn::OptionalDuration& /*loopTimeoutDuration*/) const {
+        const nn::OptionalDuration& /*loopTimeoutDuration*/,
+        const std::vector<nn::TokenValuePair>& /*hints*/,
+        const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
     return NN_ERROR() << "InvalidBurst";
 }
 
diff --git a/neuralnetworks/utils/common/src/InvalidDevice.cpp b/neuralnetworks/utils/common/src/InvalidDevice.cpp
index 535ccb4..c8cc287 100644
--- a/neuralnetworks/utils/common/src/InvalidDevice.cpp
+++ b/neuralnetworks/utils/common/src/InvalidDevice.cpp
@@ -84,7 +84,9 @@
         const nn::Model& /*model*/, nn::ExecutionPreference /*preference*/,
         nn::Priority /*priority*/, nn::OptionalTimePoint /*deadline*/,
         const std::vector<nn::SharedHandle>& /*modelCache*/,
-        const std::vector<nn::SharedHandle>& /*dataCache*/, const nn::CacheToken& /*token*/) const {
+        const std::vector<nn::SharedHandle>& /*dataCache*/, const nn::CacheToken& /*token*/,
+        const std::vector<nn::TokenValuePair>& /*hints*/,
+        const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
     return NN_ERROR() << "InvalidDevice";
 }
 
diff --git a/neuralnetworks/utils/common/src/InvalidPreparedModel.cpp b/neuralnetworks/utils/common/src/InvalidPreparedModel.cpp
index 8195462..f6f978d 100644
--- a/neuralnetworks/utils/common/src/InvalidPreparedModel.cpp
+++ b/neuralnetworks/utils/common/src/InvalidPreparedModel.cpp
@@ -27,9 +27,12 @@
 namespace android::hardware::neuralnetworks::utils {
 
 nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>
-InvalidPreparedModel::execute(const nn::Request& /*request*/, nn::MeasureTiming /*measure*/,
-                              const nn::OptionalTimePoint& /*deadline*/,
-                              const nn::OptionalDuration& /*loopTimeoutDuration*/) const {
+InvalidPreparedModel::execute(
+        const nn::Request& /*request*/, nn::MeasureTiming /*measure*/,
+        const nn::OptionalTimePoint& /*deadline*/,
+        const nn::OptionalDuration& /*loopTimeoutDuration*/,
+        const std::vector<nn::TokenValuePair>& /*hints*/,
+        const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
     return NN_ERROR() << "InvalidPreparedModel";
 }
 
@@ -38,13 +41,17 @@
         const nn::Request& /*request*/, const std::vector<nn::SyncFence>& /*waitFor*/,
         nn::MeasureTiming /*measure*/, const nn::OptionalTimePoint& /*deadline*/,
         const nn::OptionalDuration& /*loopTimeoutDuration*/,
-        const nn::OptionalDuration& /*timeoutDurationAfterFence*/) const {
+        const nn::OptionalDuration& /*timeoutDurationAfterFence*/,
+        const std::vector<nn::TokenValuePair>& /*hints*/,
+        const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
     return NN_ERROR() << "InvalidPreparedModel";
 }
 
 nn::GeneralResult<nn::SharedExecution> InvalidPreparedModel::createReusableExecution(
         const nn::Request& /*request*/, nn::MeasureTiming /*measure*/,
-        const nn::OptionalDuration& /*loopTimeoutDuration*/) const {
+        const nn::OptionalDuration& /*loopTimeoutDuration*/,
+        const std::vector<nn::TokenValuePair>& /*hints*/,
+        const std::vector<nn::ExtensionNameAndPrefix>& /*extensionNameToPrefix*/) const {
     return NN_ERROR() << "InvalidPreparedModel";
 }
 
diff --git a/neuralnetworks/utils/common/src/ProtectCallback.cpp b/neuralnetworks/utils/common/src/ProtectCallback.cpp
deleted file mode 100644
index 18e1f3b..0000000
--- a/neuralnetworks/utils/common/src/ProtectCallback.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 "ProtectCallback.h"
-
-#include <android-base/logging.h>
-#include <android-base/scopeguard.h>
-#include <android-base/thread_annotations.h>
-#include <android/hidl/base/1.0/IBase.h>
-#include <hidl/HidlSupport.h>
-#include <nnapi/Result.h>
-#include <nnapi/hal/HandleError.h>
-
-#include <algorithm>
-#include <functional>
-#include <mutex>
-#include <vector>
-
-namespace android::hardware::neuralnetworks::utils {
-
-void DeathRecipient::serviceDied(uint64_t /*cookie*/, const wp<hidl::base::V1_0::IBase>& /*who*/) {
-    std::lock_guard guard(mMutex);
-    std::for_each(mObjects.begin(), mObjects.end(),
-                  [](IProtectedCallback* killable) { killable->notifyAsDeadObject(); });
-    mObjects.clear();
-    mIsDeadObject = true;
-}
-
-void DeathRecipient::add(IProtectedCallback* killable) const {
-    CHECK(killable != nullptr);
-    std::lock_guard guard(mMutex);
-    if (mIsDeadObject) {
-        killable->notifyAsDeadObject();
-    } else {
-        mObjects.push_back(killable);
-    }
-}
-
-void DeathRecipient::remove(IProtectedCallback* killable) const {
-    CHECK(killable != nullptr);
-    std::lock_guard guard(mMutex);
-    const auto newEnd = std::remove(mObjects.begin(), mObjects.end(), killable);
-    mObjects.erase(newEnd, mObjects.end());
-}
-
-nn::GeneralResult<DeathHandler> DeathHandler::create(sp<hidl::base::V1_0::IBase> object) {
-    if (object == nullptr) {
-        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
-               << "utils::DeathHandler::create must have non-null object";
-    }
-    auto deathRecipient = sp<DeathRecipient>::make();
-
-    const auto ret = object->linkToDeath(deathRecipient, /*cookie=*/0);
-    const bool success = HANDLE_TRANSPORT_FAILURE(ret);
-    if (!success) {
-        return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "IBase::linkToDeath returned false";
-    }
-
-    return DeathHandler(std::move(object), std::move(deathRecipient));
-}
-
-DeathHandler::DeathHandler(sp<hidl::base::V1_0::IBase> object, sp<DeathRecipient> deathRecipient)
-    : mObject(std::move(object)), mDeathRecipient(std::move(deathRecipient)) {
-    CHECK(mObject != nullptr);
-    CHECK(mDeathRecipient != nullptr);
-}
-
-DeathHandler::~DeathHandler() {
-    if (mObject != nullptr && mDeathRecipient != nullptr) {
-        const auto successful = mObject->unlinkToDeath(mDeathRecipient).isOk();
-        if (!successful) {
-            LOG(ERROR) << "IBase::linkToDeath failed";
-        }
-    }
-}
-
-[[nodiscard]] base::ScopeGuard<DeathHandler::Cleanup> DeathHandler::protectCallback(
-        IProtectedCallback* killable) const {
-    CHECK(killable != nullptr);
-    mDeathRecipient->add(killable);
-    return base::make_scope_guard(
-            [deathRecipient = mDeathRecipient, killable] { deathRecipient->remove(killable); });
-}
-
-void DeathHandler::protectCallbackForLifetimeOfDeathHandler(IProtectedCallback* killable) const {
-    CHECK(killable != nullptr);
-    mDeathRecipient->add(killable);
-}
-
-}  // namespace android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/utils/common/src/ResilientBurst.cpp b/neuralnetworks/utils/common/src/ResilientBurst.cpp
index 79cbe39..bf7a8ea 100644
--- a/neuralnetworks/utils/common/src/ResilientBurst.cpp
+++ b/neuralnetworks/utils/common/src/ResilientBurst.cpp
@@ -105,37 +105,49 @@
 
 nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> ResilientBurst::execute(
         const nn::Request& request, nn::MeasureTiming measure,
-        const nn::OptionalTimePoint& deadline,
-        const nn::OptionalDuration& loopTimeoutDuration) const {
-    const auto fn = [&request, measure, deadline, loopTimeoutDuration](const nn::IBurst& burst) {
-        return burst.execute(request, measure, deadline, loopTimeoutDuration);
+        const nn::OptionalTimePoint& deadline, const nn::OptionalDuration& loopTimeoutDuration,
+        const std::vector<nn::TokenValuePair>& hints,
+        const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const {
+    const auto fn = [&request, measure, deadline, loopTimeoutDuration, &hints,
+                     &extensionNameToPrefix](const nn::IBurst& burst) {
+        return burst.execute(request, measure, deadline, loopTimeoutDuration, hints,
+                             extensionNameToPrefix);
     };
     return protect(*this, fn);
 }
 
 nn::GeneralResult<nn::SharedExecution> ResilientBurst::createReusableExecution(
         const nn::Request& request, nn::MeasureTiming measure,
-        const nn::OptionalDuration& loopTimeoutDuration) const {
+        const nn::OptionalDuration& loopTimeoutDuration,
+        const std::vector<nn::TokenValuePair>& hints,
+        const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const {
 #if 0
     auto self = shared_from_this();
-    ResilientExecution::Factory makeExecution =
-            [burst = std::move(self), request, measure, loopTimeoutDuration] {
-        return burst->createReusableExecutionInternal(request, measure, loopTimeoutDuration);
+    ResilientExecution::Factory makeExecution = [burst = std::move(self), request, measure,
+                                                 loopTimeoutDuration, &hints,
+                                                 &extensionNameToPrefix] {
+        return burst->createReusableExecutionInternal(request, measure, loopTimeoutDuration, hints,
+                                                      extensionNameToPrefix);
     };
     return ResilientExecution::create(std::move(makeExecution));
 #else
-    return createReusableExecutionInternal(request, measure, loopTimeoutDuration);
+    return createReusableExecutionInternal(request, measure, loopTimeoutDuration, hints,
+                                           extensionNameToPrefix);
 #endif
 }
 
 nn::GeneralResult<nn::SharedExecution> ResilientBurst::createReusableExecutionInternal(
         const nn::Request& request, nn::MeasureTiming measure,
-        const nn::OptionalDuration& loopTimeoutDuration) const {
+        const nn::OptionalDuration& loopTimeoutDuration,
+        const std::vector<nn::TokenValuePair>& hints,
+        const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const {
     if (!isValidInternal()) {
         return std::make_shared<const InvalidExecution>();
     }
-    const auto fn = [&request, measure, &loopTimeoutDuration](const nn::IBurst& burst) {
-        return burst.createReusableExecution(request, measure, loopTimeoutDuration);
+    const auto fn = [&request, measure, &loopTimeoutDuration, &hints,
+                     &extensionNameToPrefix](const nn::IBurst& burst) {
+        return burst.createReusableExecution(request, measure, loopTimeoutDuration, hints,
+                                             extensionNameToPrefix);
     };
     return protect(*this, fn);
 }
diff --git a/neuralnetworks/utils/common/src/ResilientDevice.cpp b/neuralnetworks/utils/common/src/ResilientDevice.cpp
index 2023c9a..a5c2640 100644
--- a/neuralnetworks/utils/common/src/ResilientDevice.cpp
+++ b/neuralnetworks/utils/common/src/ResilientDevice.cpp
@@ -179,19 +179,21 @@
 nn::GeneralResult<nn::SharedPreparedModel> ResilientDevice::prepareModel(
         const nn::Model& model, nn::ExecutionPreference preference, nn::Priority priority,
         nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
-        const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token) const {
+        const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token,
+        const std::vector<nn::TokenValuePair>& hints,
+        const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const {
 #if 0
     auto self = shared_from_this();
     ResilientPreparedModel::Factory makePreparedModel = [device = std::move(self), model,
                                                          preference, priority, deadline, modelCache,
-                                                         dataCache, token] {
+                                                         dataCache, token, hints, extensionNameToPrefix] {
         return device->prepareModelInternal(model, preference, priority, deadline, modelCache,
-                                            dataCache, token);
+                                            dataCache, token, hints, extensionNameToPrefix);
     };
     return ResilientPreparedModel::create(std::move(makePreparedModel));
 #else
-    return prepareModelInternal(model, preference, priority, deadline, modelCache, dataCache,
-                                token);
+    return prepareModelInternal(model, preference, priority, deadline, modelCache, dataCache, token,
+                                hints, extensionNameToPrefix);
 #endif
 }
 
@@ -234,14 +236,16 @@
 nn::GeneralResult<nn::SharedPreparedModel> ResilientDevice::prepareModelInternal(
         const nn::Model& model, nn::ExecutionPreference preference, nn::Priority priority,
         nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
-        const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token) const {
+        const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token,
+        const std::vector<nn::TokenValuePair>& hints,
+        const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const {
     if (!isValidInternal()) {
         return std::make_shared<const InvalidPreparedModel>();
     }
-    const auto fn = [&model, preference, priority, &deadline, &modelCache, &dataCache,
-                     &token](const nn::IDevice& device) {
+    const auto fn = [&model, preference, priority, &deadline, &modelCache, &dataCache, &token,
+                     &hints, &extensionNameToPrefix](const nn::IDevice& device) {
         return device.prepareModel(model, preference, priority, deadline, modelCache, dataCache,
-                                   token);
+                                   token, hints, extensionNameToPrefix);
     };
     return protect(*this, fn, /*blocking=*/false);
 }
diff --git a/neuralnetworks/utils/common/src/ResilientPreparedModel.cpp b/neuralnetworks/utils/common/src/ResilientPreparedModel.cpp
index 1ae19bc..b5843c0 100644
--- a/neuralnetworks/utils/common/src/ResilientPreparedModel.cpp
+++ b/neuralnetworks/utils/common/src/ResilientPreparedModel.cpp
@@ -104,43 +104,53 @@
 }
 
 nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>
-ResilientPreparedModel::execute(const nn::Request& request, nn::MeasureTiming measure,
-                                const nn::OptionalTimePoint& deadline,
-                                const nn::OptionalDuration& loopTimeoutDuration) const {
-    const auto fn = [&request, measure, &deadline,
-                     &loopTimeoutDuration](const nn::IPreparedModel& preparedModel) {
-        return preparedModel.execute(request, measure, deadline, loopTimeoutDuration);
+ResilientPreparedModel::execute(
+        const nn::Request& request, nn::MeasureTiming measure,
+        const nn::OptionalTimePoint& deadline, const nn::OptionalDuration& loopTimeoutDuration,
+        const std::vector<nn::TokenValuePair>& hints,
+        const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const {
+    const auto fn = [&request, measure, &deadline, &loopTimeoutDuration, &hints,
+                     &extensionNameToPrefix](const nn::IPreparedModel& preparedModel) {
+        return preparedModel.execute(request, measure, deadline, loopTimeoutDuration, hints,
+                                     extensionNameToPrefix);
     };
     return protect(*this, fn);
 }
 
 nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>>
-ResilientPreparedModel::executeFenced(const nn::Request& request,
-                                      const std::vector<nn::SyncFence>& waitFor,
-                                      nn::MeasureTiming measure,
-                                      const nn::OptionalTimePoint& deadline,
-                                      const nn::OptionalDuration& loopTimeoutDuration,
-                                      const nn::OptionalDuration& timeoutDurationAfterFence) const {
+ResilientPreparedModel::executeFenced(
+        const nn::Request& request, const std::vector<nn::SyncFence>& waitFor,
+        nn::MeasureTiming measure, const nn::OptionalTimePoint& deadline,
+        const nn::OptionalDuration& loopTimeoutDuration,
+        const nn::OptionalDuration& timeoutDurationAfterFence,
+        const std::vector<nn::TokenValuePair>& hints,
+        const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const {
     const auto fn = [&request, &waitFor, measure, &deadline, &loopTimeoutDuration,
-                     &timeoutDurationAfterFence](const nn::IPreparedModel& preparedModel) {
+                     &timeoutDurationAfterFence, &hints,
+                     &extensionNameToPrefix](const nn::IPreparedModel& preparedModel) {
         return preparedModel.executeFenced(request, waitFor, measure, deadline, loopTimeoutDuration,
-                                           timeoutDurationAfterFence);
+                                           timeoutDurationAfterFence, hints, extensionNameToPrefix);
     };
     return protect(*this, fn);
 }
 
 nn::GeneralResult<nn::SharedExecution> ResilientPreparedModel::createReusableExecution(
         const nn::Request& request, nn::MeasureTiming measure,
-        const nn::OptionalDuration& loopTimeoutDuration) const {
+        const nn::OptionalDuration& loopTimeoutDuration,
+        const std::vector<nn::TokenValuePair>& hints,
+        const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const {
 #if 0
     auto self = shared_from_this();
-    ResilientExecution::Factory makeExecution =
-            [preparedModel = std::move(self), request, measure, loopTimeoutDuration] {
-        return preparedModel->createReusableExecutionInternal(request, measure, loopTimeoutDuration);
+    ResilientExecution::Factory makeExecution = [preparedModel = std::move(self), request, measure,
+                                                 loopTimeoutDuration, hints,
+                                                 extensionNameToPrefix] {
+        return preparedModel->createReusableExecutionInternal(request, measure, loopTimeoutDuration,
+                                                              hints, extensionNameToPrefix);
     };
     return ResilientExecution::create(std::move(makeExecution));
 #else
-    return createReusableExecutionInternal(request, measure, loopTimeoutDuration);
+    return createReusableExecutionInternal(request, measure, loopTimeoutDuration, hints,
+                                           extensionNameToPrefix);
 #endif
 }
 
@@ -159,13 +169,16 @@
 
 nn::GeneralResult<nn::SharedExecution> ResilientPreparedModel::createReusableExecutionInternal(
         const nn::Request& request, nn::MeasureTiming measure,
-        const nn::OptionalDuration& loopTimeoutDuration) const {
+        const nn::OptionalDuration& loopTimeoutDuration,
+        const std::vector<nn::TokenValuePair>& hints,
+        const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) const {
     if (!isValidInternal()) {
         return std::make_shared<const InvalidExecution>();
     }
-    const auto fn = [&request, measure,
-                     &loopTimeoutDuration](const nn::IPreparedModel& preparedModel) {
-        return preparedModel.createReusableExecution(request, measure, loopTimeoutDuration);
+    const auto fn = [&request, measure, &loopTimeoutDuration, &hints,
+                     &extensionNameToPrefix](const nn::IPreparedModel& preparedModel) {
+        return preparedModel.createReusableExecution(request, measure, loopTimeoutDuration, hints,
+                                                     extensionNameToPrefix);
     };
     return protect(*this, fn);
 }
diff --git a/neuralnetworks/utils/common/test/MockDevice.h b/neuralnetworks/utils/common/test/MockDevice.h
index a9428bc..a0fc5c3 100644
--- a/neuralnetworks/utils/common/test/MockDevice.h
+++ b/neuralnetworks/utils/common/test/MockDevice.h
@@ -39,7 +39,9 @@
     MOCK_METHOD(GeneralResult<SharedPreparedModel>, prepareModel,
                 (const Model& model, ExecutionPreference preference, Priority priority,
                  OptionalTimePoint deadline, const std::vector<SharedHandle>& modelCache,
-                 const std::vector<SharedHandle>& dataCache, const CacheToken& token),
+                 const std::vector<SharedHandle>& dataCache, const CacheToken& token,
+                 const std::vector<TokenValuePair>& hints,
+                 const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix),
                 (const, override));
     MOCK_METHOD(GeneralResult<SharedPreparedModel>, prepareModelFromCache,
                 (OptionalTimePoint deadline, const std::vector<SharedHandle>& modelCache,
diff --git a/neuralnetworks/utils/common/test/MockPreparedModel.h b/neuralnetworks/utils/common/test/MockPreparedModel.h
index c8ce006..b8613b2 100644
--- a/neuralnetworks/utils/common/test/MockPreparedModel.h
+++ b/neuralnetworks/utils/common/test/MockPreparedModel.h
@@ -27,17 +27,23 @@
   public:
     MOCK_METHOD((ExecutionResult<std::pair<std::vector<OutputShape>, Timing>>), execute,
                 (const Request& request, MeasureTiming measure, const OptionalTimePoint& deadline,
-                 const OptionalDuration& loopTimeoutDuration),
+                 const OptionalDuration& loopTimeoutDuration,
+                 const std::vector<TokenValuePair>& hints,
+                 const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix),
                 (const, override));
     MOCK_METHOD((GeneralResult<std::pair<SyncFence, ExecuteFencedInfoCallback>>), executeFenced,
                 (const Request& request, const std::vector<SyncFence>& waitFor,
                  MeasureTiming measure, const OptionalTimePoint& deadline,
                  const OptionalDuration& loopTimeoutDuration,
-                 const OptionalDuration& timeoutDurationAfterFence),
+                 const OptionalDuration& timeoutDurationAfterFence,
+                 const std::vector<TokenValuePair>& hints,
+                 const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix),
                 (const, override));
     MOCK_METHOD((GeneralResult<SharedExecution>), createReusableExecution,
-                (const nn::Request& request, nn::MeasureTiming measure,
-                 const nn::OptionalDuration& loopTimeoutDuration),
+                (const Request& request, MeasureTiming measure,
+                 const OptionalDuration& loopTimeoutDuration,
+                 const std::vector<TokenValuePair>& hints,
+                 const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix),
                 (const, override));
     MOCK_METHOD(GeneralResult<SharedBurst>, configureExecutionBurst, (), (const, override));
     MOCK_METHOD(std::any, getUnderlyingResource, (), (const, override));
diff --git a/neuralnetworks/utils/common/test/ResilientDeviceTest.cpp b/neuralnetworks/utils/common/test/ResilientDeviceTest.cpp
index 3abd724..d9b8505 100644
--- a/neuralnetworks/utils/common/test/ResilientDeviceTest.cpp
+++ b/neuralnetworks/utils/common/test/ResilientDeviceTest.cpp
@@ -28,7 +28,6 @@
 namespace {
 
 using ::testing::_;
-using ::testing::InvokeWithoutArgs;
 using ::testing::Return;
 
 using SharedMockDevice = std::shared_ptr<const nn::MockDevice>;
@@ -54,7 +53,7 @@
     // Setup default actions for each relevant call.
     constexpr auto getName_ret = []() -> const std::string& { return kName; };
     constexpr auto getVersionString_ret = []() -> const std::string& { return kVersionString; };
-    constexpr auto kFeatureLevel = nn::Version::ANDROID_OC_MR1;
+    constexpr auto kFeatureLevel = nn::kVersionFeatureLevel1;
     constexpr auto kDeviceType = nn::DeviceType::ACCELERATOR;
     constexpr auto getSupportedExtensions_ret = []() -> const std::vector<nn::Extension>& {
         return kExtensions;
@@ -142,7 +141,7 @@
 TEST(ResilientDeviceTest, getFeatureLevel) {
     // setup call
     const auto [mockDevice, mockDeviceFactory, device] = setup();
-    constexpr auto kFeatureLevel = nn::Version::ANDROID_OC_MR1;
+    constexpr auto kFeatureLevel = nn::kVersionFeatureLevel1;
     EXPECT_CALL(*mockDevice, getFeatureLevel()).Times(1).WillOnce(Return(kFeatureLevel));
 
     // run test
@@ -310,12 +309,12 @@
     // setup call
     const auto [mockDevice, mockDeviceFactory, device] = setup();
     const auto mockPreparedModel = std::make_shared<const nn::MockPreparedModel>();
-    EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _))
+    EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _, _, _))
             .Times(1)
             .WillOnce(Return(mockPreparedModel));
 
     // run test
-    const auto result = device->prepareModel({}, {}, {}, {}, {}, {}, {});
+    const auto result = device->prepareModel({}, {}, {}, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_TRUE(result.has_value())
@@ -325,12 +324,12 @@
 TEST(ResilientDeviceTest, prepareModelError) {
     // setup call
     const auto [mockDevice, mockDeviceFactory, device] = setup();
-    EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _))
+    EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _, _, _))
             .Times(1)
             .WillOnce(kReturnGeneralFailure);
 
     // run test
-    const auto result = device->prepareModel({}, {}, {}, {}, {}, {}, {});
+    const auto result = device->prepareModel({}, {}, {}, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -340,13 +339,13 @@
 TEST(ResilientDeviceTest, prepareModelDeadObjectFailedRecovery) {
     // setup call
     const auto [mockDevice, mockDeviceFactory, device] = setup();
-    EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _))
+    EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _, _, _))
             .Times(1)
             .WillOnce(kReturnDeadObject);
     EXPECT_CALL(*mockDeviceFactory, Call(false)).Times(1).WillOnce(kReturnGeneralFailure);
 
     // run test
-    const auto result = device->prepareModel({}, {}, {}, {}, {}, {}, {});
+    const auto result = device->prepareModel({}, {}, {}, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -356,18 +355,18 @@
 TEST(ResilientDeviceTest, prepareModelDeadObjectSuccessfulRecovery) {
     // setup call
     const auto [mockDevice, mockDeviceFactory, device] = setup();
-    EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _))
+    EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _, _, _))
             .Times(1)
             .WillOnce(kReturnDeadObject);
     const auto recoveredMockDevice = createConfiguredMockDevice();
     const auto mockPreparedModel = std::make_shared<const nn::MockPreparedModel>();
-    EXPECT_CALL(*recoveredMockDevice, prepareModel(_, _, _, _, _, _, _))
+    EXPECT_CALL(*recoveredMockDevice, prepareModel(_, _, _, _, _, _, _, _, _))
             .Times(1)
             .WillOnce(Return(mockPreparedModel));
     EXPECT_CALL(*mockDeviceFactory, Call(false)).Times(1).WillOnce(Return(recoveredMockDevice));
 
     // run test
-    const auto result = device->prepareModel({}, {}, {}, {}, {}, {}, {});
+    const auto result = device->prepareModel({}, {}, {}, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_TRUE(result.has_value())
@@ -592,7 +591,7 @@
     const auto recoveredMockDevice = createConfiguredMockDevice();
     EXPECT_CALL(*recoveredMockDevice, getFeatureLevel())
             .Times(1)
-            .WillOnce(Return(nn::Version::ANDROID_P));
+            .WillOnce(Return(nn::kVersionFeatureLevel2));
     EXPECT_CALL(*mockDeviceFactory, Call(false)).Times(1).WillOnce(Return(recoveredMockDevice));
 
     // run test
@@ -680,7 +679,7 @@
     device->recover(mockDevice.get(), /*blocking=*/false);
 
     // run test
-    auto result = device->prepareModel({}, {}, {}, {}, {}, {}, {});
+    auto result = device->prepareModel({}, {}, {}, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_TRUE(result.has_value())
diff --git a/neuralnetworks/utils/common/test/ResilientPreparedModelTest.cpp b/neuralnetworks/utils/common/test/ResilientPreparedModelTest.cpp
index d396ca8..276bfba 100644
--- a/neuralnetworks/utils/common/test/ResilientPreparedModelTest.cpp
+++ b/neuralnetworks/utils/common/test/ResilientPreparedModelTest.cpp
@@ -104,12 +104,12 @@
 TEST(ResilientPreparedModelTest, execute) {
     // setup call
     const auto [mockPreparedModel, mockPreparedModelFactory, preparedModel] = setup();
-    EXPECT_CALL(*mockPreparedModel, execute(_, _, _, _))
+    EXPECT_CALL(*mockPreparedModel, execute(_, _, _, _, _, _))
             .Times(1)
             .WillOnce(Return(kNoExecutionError));
 
     // run test
-    const auto result = preparedModel->execute({}, {}, {}, {});
+    const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_TRUE(result.has_value())
@@ -119,10 +119,12 @@
 TEST(ResilientPreparedModelTest, executeError) {
     // setup call
     const auto [mockPreparedModel, mockPreparedModelFactory, preparedModel] = setup();
-    EXPECT_CALL(*mockPreparedModel, execute(_, _, _, _)).Times(1).WillOnce(kReturnGeneralFailure);
+    EXPECT_CALL(*mockPreparedModel, execute(_, _, _, _, _, _))
+            .Times(1)
+            .WillOnce(kReturnGeneralFailure);
 
     // run test
-    const auto result = preparedModel->execute({}, {}, {}, {});
+    const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -132,12 +134,12 @@
 TEST(ResilientPreparedModelTest, executeDeadObjectFailedRecovery) {
     // setup call
     const auto [mockPreparedModel, mockPreparedModelFactory, preparedModel] = setup();
-    EXPECT_CALL(*mockPreparedModel, execute(_, _, _, _)).Times(1).WillOnce(kReturnDeadObject);
+    EXPECT_CALL(*mockPreparedModel, execute(_, _, _, _, _, _)).Times(1).WillOnce(kReturnDeadObject);
     constexpr auto ret = [] { return nn::error(nn::ErrorStatus::GENERAL_FAILURE); };
     EXPECT_CALL(*mockPreparedModelFactory, Call()).Times(1).WillOnce(ret);
 
     // run test
-    const auto result = preparedModel->execute({}, {}, {}, {});
+    const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -147,9 +149,9 @@
 TEST(ResilientPreparedModelTest, executeDeadObjectSuccessfulRecovery) {
     // setup call
     const auto [mockPreparedModel, mockPreparedModelFactory, preparedModel] = setup();
-    EXPECT_CALL(*mockPreparedModel, execute(_, _, _, _)).Times(1).WillOnce(kReturnDeadObject);
+    EXPECT_CALL(*mockPreparedModel, execute(_, _, _, _, _, _)).Times(1).WillOnce(kReturnDeadObject);
     const auto recoveredMockPreparedModel = createConfiguredMockPreparedModel();
-    EXPECT_CALL(*recoveredMockPreparedModel, execute(_, _, _, _))
+    EXPECT_CALL(*recoveredMockPreparedModel, execute(_, _, _, _, _, _))
             .Times(1)
             .WillOnce(Return(kNoExecutionError));
     EXPECT_CALL(*mockPreparedModelFactory, Call())
@@ -157,7 +159,7 @@
             .WillOnce(Return(recoveredMockPreparedModel));
 
     // run test
-    const auto result = preparedModel->execute({}, {}, {}, {});
+    const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_TRUE(result.has_value())
@@ -167,12 +169,12 @@
 TEST(ResilientPreparedModelTest, executeFenced) {
     // setup call
     const auto [mockPreparedModel, mockPreparedModelFactory, preparedModel] = setup();
-    EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _))
+    EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _, _))
             .Times(1)
             .WillOnce(Return(kNoFencedExecutionError));
 
     // run test
-    const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
+    const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_TRUE(result.has_value())
@@ -182,12 +184,12 @@
 TEST(ResilientPreparedModelTest, executeFencedError) {
     // setup call
     const auto [mockPreparedModel, mockPreparedModelFactory, preparedModel] = setup();
-    EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _))
+    EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _, _))
             .Times(1)
             .WillOnce(kReturnGeneralFailure);
 
     // run test
-    const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
+    const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -197,13 +199,13 @@
 TEST(ResilientPreparedModelTest, executeFencedDeadObjectFailedRecovery) {
     // setup call
     const auto [mockPreparedModel, mockPreparedModelFactory, preparedModel] = setup();
-    EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _))
+    EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _, _))
             .Times(1)
             .WillOnce(kReturnDeadObject);
     EXPECT_CALL(*mockPreparedModelFactory, Call()).Times(1).WillOnce(kReturnGeneralFailure);
 
     // run test
-    const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
+    const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
@@ -213,11 +215,11 @@
 TEST(ResilientPreparedModelTest, executeFencedDeadObjectSuccessfulRecovery) {
     // setup call
     const auto [mockPreparedModel, mockPreparedModelFactory, preparedModel] = setup();
-    EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _))
+    EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _, _))
             .Times(1)
             .WillOnce(kReturnDeadObject);
     const auto recoveredMockPreparedModel = createConfiguredMockPreparedModel();
-    EXPECT_CALL(*recoveredMockPreparedModel, executeFenced(_, _, _, _, _, _))
+    EXPECT_CALL(*recoveredMockPreparedModel, executeFenced(_, _, _, _, _, _, _, _))
             .Times(1)
             .WillOnce(Return(kNoFencedExecutionError));
     EXPECT_CALL(*mockPreparedModelFactory, Call())
@@ -225,7 +227,7 @@
             .WillOnce(Return(recoveredMockPreparedModel));
 
     // run test
-    const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
+    const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
 
     // verify result
     ASSERT_TRUE(result.has_value())
@@ -235,12 +237,12 @@
 TEST(ResilientPreparedModelTest, createReusableExecution) {
     // setup call
     const auto [mockPreparedModel, mockPreparedModelFactory, preparedModel] = setup();
-    EXPECT_CALL(*mockPreparedModel, createReusableExecution(_, _, _))
+    EXPECT_CALL(*mockPreparedModel, createReusableExecution(_, _, _, _, _))
             .Times(1)
             .WillOnce(Return(kNoCreateReusableExecutionError));
 
     // run test
-    const auto result = preparedModel->createReusableExecution({}, {}, {});
+    const auto result = preparedModel->createReusableExecution({}, {}, {}, {}, {});
 
     // verify result
     ASSERT_TRUE(result.has_value())
@@ -250,12 +252,12 @@
 TEST(ResilientPreparedModelTest, createReusableExecutionError) {
     // setup call
     const auto [mockPreparedModel, mockPreparedModelFactory, preparedModel] = setup();
-    EXPECT_CALL(*mockPreparedModel, createReusableExecution(_, _, _))
+    EXPECT_CALL(*mockPreparedModel, createReusableExecution(_, _, _, _, _))
             .Times(1)
             .WillOnce(kReturnGeneralFailure);
 
     // run test
-    const auto result = preparedModel->createReusableExecution({}, {}, {});
+    const auto result = preparedModel->createReusableExecution({}, {}, {}, {}, {});
 
     // verify result
     ASSERT_FALSE(result.has_value());
diff --git a/neuralnetworks/utils/service/Android.bp b/neuralnetworks/utils/service/Android.bp
index ab996ce..452078b 100644
--- a/neuralnetworks/utils/service/Android.bp
+++ b/neuralnetworks/utils/service/Android.bp
@@ -25,25 +25,23 @@
 
 cc_library_static {
     name: "neuralnetworks_utils_hal_service",
-    defaults: ["neuralnetworks_utils_defaults"],
+    defaults: [
+        "neuralnetworks_use_latest_utils_hal_aidl",
+        "neuralnetworks_utils_defaults",
+    ],
     srcs: ["src/*"],
     local_include_dirs: ["include/nnapi/hal"],
     export_include_dirs: ["include"],
     static_libs: [
+        "android.hardware.neuralnetworks@1.0",
+        "android.hardware.neuralnetworks@1.1",
+        "android.hardware.neuralnetworks@1.2",
+        "android.hardware.neuralnetworks@1.3",
         "neuralnetworks_types",
         "neuralnetworks_utils_hal_1_0",
         "neuralnetworks_utils_hal_1_1",
         "neuralnetworks_utils_hal_1_2",
         "neuralnetworks_utils_hal_1_3",
-        "neuralnetworks_utils_hal_aidl",
         "neuralnetworks_utils_hal_common",
     ],
-    shared_libs: [
-        "android.hardware.neuralnetworks-V2-ndk_platform",
-        "android.hardware.neuralnetworks@1.0",
-        "android.hardware.neuralnetworks@1.1",
-        "android.hardware.neuralnetworks@1.2",
-        "android.hardware.neuralnetworks@1.3",
-        "libbinder_ndk",
-    ],
 }
diff --git a/neuralnetworks/utils/service/include/nnapi/hal/Service.h b/neuralnetworks/utils/service/include/nnapi/hal/Service.h
index 2fd5237..38d2a54 100644
--- a/neuralnetworks/utils/service/include/nnapi/hal/Service.h
+++ b/neuralnetworks/utils/service/include/nnapi/hal/Service.h
@@ -24,12 +24,16 @@
 
 namespace android::hardware::neuralnetworks::service {
 
-struct SharedDeviceAndUpdatability {
-    nn::SharedDevice device;
-    bool isDeviceUpdatable = false;
-};
-
-std::vector<SharedDeviceAndUpdatability> getDevices(bool includeUpdatableDrivers);
+/**
+ * @brief Get the NNAPI sAIDL and HIDL services declared in the VINTF.
+ *
+ * @pre maxFeatureLevelAllowed >= Version::Level::FEATURE_LEVEL_5
+ *
+ * @param maxFeatureLevelAllowed Maximum version of driver allowed to be used. Any driver version
+ *     exceeding this must be clamped to `maxFeatureLevelAllowed`.
+ * @return A list of devices and whether each device is updatable or not.
+ */
+std::vector<nn::SharedDevice> getDevices(nn::Version::Level maxFeatureLevelAllowed);
 
 }  // namespace android::hardware::neuralnetworks::service
 
diff --git a/neuralnetworks/utils/service/src/Service.cpp b/neuralnetworks/utils/service/src/Service.cpp
index 2286288..dd37dae 100644
--- a/neuralnetworks/utils/service/src/Service.cpp
+++ b/neuralnetworks/utils/service/src/Service.cpp
@@ -51,7 +51,7 @@
 using getDeviceFn = std::add_pointer_t<nn::GeneralResult<nn::SharedDevice>(const std::string&)>;
 
 void getHidlDevicesForVersion(const std::string& descriptor, getDeviceFn getDevice,
-                              std::vector<SharedDeviceAndUpdatability>* devices,
+                              std::vector<nn::SharedDevice>* devices,
                               std::unordered_set<std::string>* registeredDevices) {
     CHECK(devices != nullptr);
     CHECK(registeredDevices != nullptr);
@@ -63,7 +63,7 @@
             if (maybeDevice.has_value()) {
                 auto device = std::move(maybeDevice).value();
                 CHECK(device != nullptr);
-                devices->push_back({.device = std::move(device)});
+                devices->push_back(std::move(device));
             } else {
                 LOG(ERROR) << "getDevice(" << name << ") failed with " << maybeDevice.error().code
                            << ": " << maybeDevice.error().message;
@@ -72,9 +72,9 @@
     }
 }
 
-void getAidlDevices(std::vector<SharedDeviceAndUpdatability>* devices,
+void getAidlDevices(std::vector<nn::SharedDevice>* devices,
                     std::unordered_set<std::string>* registeredDevices,
-                    bool includeUpdatableDrivers) {
+                    nn::Version::Level maxFeatureLevelAllowed) {
     CHECK(devices != nullptr);
     CHECK(registeredDevices != nullptr);
 
@@ -91,21 +91,12 @@
     }
 
     for (const auto& name : names) {
-        bool isDeviceUpdatable = false;
-        if (__builtin_available(android __NNAPI_AIDL_MIN_ANDROID_API__, *)) {
-            const auto instance = std::string(aidl_hal::IDevice::descriptor) + '/' + name;
-            isDeviceUpdatable = AServiceManager_isUpdatableViaApex(instance.c_str());
-        }
-        if (isDeviceUpdatable && !includeUpdatableDrivers) {
-            continue;
-        }
         if (const auto [it, unregistered] = registeredDevices->insert(name); unregistered) {
-            auto maybeDevice = aidl_hal::utils::getDevice(name);
+            auto maybeDevice = aidl_hal::utils::getDevice(name, maxFeatureLevelAllowed);
             if (maybeDevice.has_value()) {
                 auto device = std::move(maybeDevice).value();
                 CHECK(device != nullptr);
-                devices->push_back(
-                        {.device = std::move(device), .isDeviceUpdatable = isDeviceUpdatable});
+                devices->push_back(std::move(device));
             } else {
                 LOG(ERROR) << "getDevice(" << name << ") failed with " << maybeDevice.error().code
                            << ": " << maybeDevice.error().message;
@@ -116,11 +107,13 @@
 
 }  // namespace
 
-std::vector<SharedDeviceAndUpdatability> getDevices(bool includeUpdatableDrivers) {
-    std::vector<SharedDeviceAndUpdatability> devices;
+std::vector<nn::SharedDevice> getDevices(nn::Version::Level maxFeatureLevelAllowed) {
+    std::vector<nn::SharedDevice> devices;
     std::unordered_set<std::string> registeredDevices;
 
-    getAidlDevices(&devices, &registeredDevices, includeUpdatableDrivers);
+    CHECK_GE(maxFeatureLevelAllowed, nn::Version::Level::FEATURE_LEVEL_5);
+
+    getAidlDevices(&devices, &registeredDevices, maxFeatureLevelAllowed);
 
     getHidlDevicesForVersion(V1_3::IDevice::descriptor, &V1_3::utils::getDevice, &devices,
                              &registeredDevices);
diff --git a/nfc/1.0/vts/functional/OWNERS b/nfc/1.0/vts/functional/OWNERS
new file mode 100644
index 0000000..bf0e58b
--- /dev/null
+++ b/nfc/1.0/vts/functional/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 48448
+georgekgchang@google.com
+jackcwyu@google.com
diff --git a/nfc/1.1/vts/functional/OWNERS b/nfc/1.1/vts/functional/OWNERS
new file mode 100644
index 0000000..bf0e58b
--- /dev/null
+++ b/nfc/1.1/vts/functional/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 48448
+georgekgchang@google.com
+jackcwyu@google.com
diff --git a/nfc/1.2/vts/functional/OWNERS b/nfc/1.2/vts/functional/OWNERS
new file mode 100644
index 0000000..c506226
--- /dev/null
+++ b/nfc/1.2/vts/functional/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 48448
+georgekgchang@google.com
+jackcwyu@google.com
+alisher@google.com
diff --git a/nfc/OWNERS b/nfc/OWNERS
new file mode 100644
index 0000000..7867204
--- /dev/null
+++ b/nfc/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 48448
+alisher@google.com
+georgekgchang@google.com
+jackcwyu@google.com
+
+
diff --git a/nfc/aidl/Android.bp b/nfc/aidl/Android.bp
new file mode 100644
index 0000000..30365f6
--- /dev/null
+++ b/nfc/aidl/Android.bp
@@ -0,0 +1,43 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+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.nfc",
+    vendor_available: true,
+    srcs: ["android/hardware/nfc/*.aidl"],
+    stability: "vintf",
+    backend: {
+        cpp: {
+            enabled: false,
+        },
+        java: {
+            sdk_version: "module_current",
+            enabled: false,
+        },
+        ndk: {
+            vndk: {
+                enabled: true,
+            },
+        },
+    },
+}
diff --git a/nfc/aidl/TEST_MAPPING b/nfc/aidl/TEST_MAPPING
new file mode 100644
index 0000000..3a10084
--- /dev/null
+++ b/nfc/aidl/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "VtsAidlHalNfcTargetTest"
+    }
+  ]
+}
diff --git a/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/INfc.aidl b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/INfc.aidl
new file mode 100644
index 0000000..7a0ae54
--- /dev/null
+++ b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/INfc.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.nfc;
+@VintfStability
+interface INfc {
+  void open(in android.hardware.nfc.INfcClientCallback clientCallback);
+  void close(in android.hardware.nfc.NfcCloseType type);
+  void coreInitialized();
+  void factoryReset();
+  android.hardware.nfc.NfcConfig getConfig();
+  void powerCycle();
+  void preDiscover();
+  int write(in byte[] data);
+  void setEnableVerboseLogging(in boolean enable);
+  boolean isVerboseLoggingEnabled();
+}
diff --git a/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/INfcClientCallback.aidl b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/INfcClientCallback.aidl
new file mode 100644
index 0000000..8150e81
--- /dev/null
+++ b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/INfcClientCallback.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.nfc;
+@VintfStability
+interface INfcClientCallback {
+  void sendData(in byte[] data);
+  void sendEvent(in android.hardware.nfc.NfcEvent event, in android.hardware.nfc.NfcStatus status);
+}
diff --git a/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcCloseType.aidl b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcCloseType.aidl
new file mode 100644
index 0000000..7d44d48
--- /dev/null
+++ b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcCloseType.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.nfc;
+@Backing(type="int") @VintfStability
+enum NfcCloseType {
+  DISABLE = 0,
+  HOST_SWITCHED_OFF = 1,
+}
diff --git a/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcConfig.aidl b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcConfig.aidl
new file mode 100644
index 0000000..92e0a9a
--- /dev/null
+++ b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcConfig.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.nfc;
+@VintfStability
+parcelable NfcConfig {
+  boolean nfaPollBailOutMode;
+  android.hardware.nfc.PresenceCheckAlgorithm presenceCheckAlgorithm;
+  android.hardware.nfc.ProtocolDiscoveryConfig nfaProprietaryCfg;
+  byte defaultOffHostRoute;
+  byte defaultOffHostRouteFelica;
+  byte defaultSystemCodeRoute;
+  byte defaultSystemCodePowerState;
+  byte defaultRoute;
+  byte offHostESEPipeId;
+  byte offHostSIMPipeId;
+  int maxIsoDepTransceiveLength;
+  byte[] hostAllowlist;
+  byte[] offHostRouteUicc;
+  byte[] offHostRouteEse;
+  byte defaultIsoDepRoute;
+}
diff --git a/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcEvent.aidl b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcEvent.aidl
new file mode 100644
index 0000000..dda258e
--- /dev/null
+++ b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcEvent.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.nfc;
+@Backing(type="int") @VintfStability
+enum NfcEvent {
+  OPEN_CPLT = 0,
+  CLOSE_CPLT = 1,
+  POST_INIT_CPLT = 2,
+  PRE_DISCOVER_CPLT = 3,
+  HCI_NETWORK_RESET = 4,
+  ERROR = 5,
+}
diff --git a/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcStatus.aidl b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcStatus.aidl
new file mode 100644
index 0000000..2632480
--- /dev/null
+++ b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/NfcStatus.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.nfc;
+@Backing(type="int") @VintfStability
+enum NfcStatus {
+  OK = 0,
+  FAILED = 1,
+  ERR_TRANSPORT = 2,
+  ERR_CMD_TIMEOUT = 3,
+  REFUSED = 4,
+}
diff --git a/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/PresenceCheckAlgorithm.aidl b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/PresenceCheckAlgorithm.aidl
new file mode 100644
index 0000000..9a9be21
--- /dev/null
+++ b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/PresenceCheckAlgorithm.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.nfc;
+@Backing(type="byte") @VintfStability
+enum PresenceCheckAlgorithm {
+  DEFAULT = 0,
+  I_BLOCK = 1,
+  ISO_DEP_NAK = 2,
+}
diff --git a/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/ProtocolDiscoveryConfig.aidl b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/ProtocolDiscoveryConfig.aidl
new file mode 100644
index 0000000..021dfe2
--- /dev/null
+++ b/nfc/aidl/aidl_api/android.hardware.nfc/current/android/hardware/nfc/ProtocolDiscoveryConfig.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.nfc;
+@VintfStability
+parcelable ProtocolDiscoveryConfig {
+  byte protocol18092Active;
+  byte protocolBPrime;
+  byte protocolDual;
+  byte protocol15693;
+  byte protocolKovio;
+  byte protocolMifare;
+  byte discoveryPollKovio;
+  byte discoveryPollBPrime;
+  byte discoveryListenBPrime;
+}
diff --git a/nfc/aidl/android/hardware/nfc/INfc.aidl b/nfc/aidl/android/hardware/nfc/INfc.aidl
new file mode 100644
index 0000000..662f8d4
--- /dev/null
+++ b/nfc/aidl/android/hardware/nfc/INfc.aidl
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.nfc;
+
+import android.hardware.nfc.INfcClientCallback;
+import android.hardware.nfc.NfcCloseType;
+import android.hardware.nfc.NfcConfig;
+import android.hardware.nfc.NfcStatus;
+
+@VintfStability
+interface INfc {
+    /**
+     * Opens the NFC controller device and performs initialization.
+     * This may include patch download and other vendor-specific initialization.
+     *
+     * If open completes successfully, the controller must be ready to perform NCI
+     * initialization - ie accept CORE_RESET and subsequent commands through the write()
+     * call.
+     *
+     * Returns ok() if initialization starts successfully.
+     * If open() returns ok(), the NCI stack must wait for a NfcEvent.OPEN_CPLT
+     * callback before continuing.
+     * If a NfcEvent.OPEN_CPLT callback received with status NfcStatus::OK, the controller
+     * must be ready to perform  NCI initialization - ie accept CORE_RESET and subsequent
+     * commands through the write() call.
+     */
+    void open(in INfcClientCallback clientCallback);
+
+    /**
+     * Close the NFC HAL and setup NFC controller close type.
+     * Associated resources such as clientCallback must be released.
+     * The clientCallback reference from open() must be invalid after close().
+     * If close() returns ok(), the NCI stack must wait for a NfcEvent.CLOSE_CPLT
+     * callback before continuing.
+     * Returns an error if close may be called more than once.
+     * Calls to any other method which expect a callback after this must return
+     * a service-specific error NfcStatus::FAILED.
+     * HAL close automatically if the client drops the reference to the HAL or
+     * crashes.
+     */
+    void close(in NfcCloseType type);
+
+    /**
+     * coreInitialized() is called after the CORE_INIT_RSP is received from the
+     * NFCC. At this time, the HAL can do any chip-specific configuration.
+     *
+     * If coreInitialized() returns ok(), the NCI stack must wait for a
+     * NfcEvent.POST_INIT_CPLT before continuing.
+     * If coreInitialized() returns an error, the NCI stack must continue immediately.
+     *
+     * coreInitialized() must be called after open() registers the clientCallback
+     * or return a service-specific error NfcStatus::FAILED directly.
+     *
+     */
+    void coreInitialized();
+
+    /**
+     * Clears the NFC chip.
+     *
+     * Must be called during factory reset and/or before the first time the HAL is
+     * initialized after a factory reset.
+     */
+    void factoryReset();
+
+    /**
+     * Fetches vendor specific configurations.
+     * @return NfcConfig indicates support for certain features and
+     * populates the vendor specific configs.
+     */
+    NfcConfig getConfig();
+
+    /**
+     * Restart controller by power cyle;
+     * It's similar to open but just reset the controller without initialize all the
+     * resources.
+     *
+     * If powerCycle() returns ok(), the NCI stack must wait for a NfcEvent.OPEN_CPLT
+     * before continuing.
+     *
+     * powerCycle() must be called after open() registers the clientCallback
+     * or return a service-specific error NfcStatus::FAILED directly.
+     */
+    void powerCycle();
+
+    /**
+     * preDiscover is called every time before starting RF discovery.
+     * It is a good place to do vendor-specific configuration that must be
+     * performed every time RF discovery is about to be started.
+     *
+     * If preDiscover() returns ok(), the NCI stack must wait for a
+     * NfcEvent.PREDISCOVER_CPLT before continuing.
+     *
+     * preDiscover() must be called after open() registers the clientCallback
+     * or return a service-specific error NfcStatus::FAILED directly.
+     *
+     * If preDiscover() reports an error, the NCI stack must start RF discovery immediately.
+     */
+    void preDiscover();
+
+    /**
+     * Performs an NCI write.
+     *
+     * This method may queue writes and return immediately. The only
+     * requirement is that the writes are executed in order.
+     *
+     * @param data
+     * Data packet to transmit NCI Commands and Data Messages over write.
+     * Detailed format is defined in NFC Controller Interface (NCI) Technical Specification.
+     * https://nfc-forum.org/our-work/specification-releases/
+     *
+     * @return number of bytes written to the NFCC.
+     */
+    int write(in byte[] data);
+
+    /**
+     * Set the logging flag for NFC HAL to enable it's verbose logging.
+     * If verbose logging is not supported, the call must not have any effect on logging verbosity.
+     * However, isVerboseLoggingEnabled() must still return the value set by the last call to
+     * setEnableVerboseLogging().
+     * @param enable for setting the verbose logging flag to HAL
+     */
+    void setEnableVerboseLogging(in boolean enable);
+
+    /**
+     * Get the verbose logging flag value from NFC HAL.
+     * @return true if verbose logging flag value is enabled, false if disabled.
+     */
+    boolean isVerboseLoggingEnabled();
+}
diff --git a/nfc/aidl/android/hardware/nfc/INfcClientCallback.aidl b/nfc/aidl/android/hardware/nfc/INfcClientCallback.aidl
new file mode 100644
index 0000000..43d4f5c
--- /dev/null
+++ b/nfc/aidl/android/hardware/nfc/INfcClientCallback.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.nfc;
+
+import android.hardware.nfc.NfcEvent;
+import android.hardware.nfc.NfcStatus;
+
+@VintfStability
+interface INfcClientCallback {
+    /**
+     * The callback passed in from the NFC stack that the HAL
+     * can use to pass incomming response data to the stack.
+     *
+     * @param data
+     * Data packet to transmit NCI Responses, Notifications, and Data
+     * Messages over sendData.
+     * Detailed format is defined in NFC Controller Interface (NCI) Technical Specification.
+     * https://nfc-forum.org/our-work/specification-releases/
+     */
+    void sendData(in byte[] data);
+
+    /**
+     * The callback passed in from the NFC stack that the HAL
+     * can use to pass events back to the stack.
+     */
+    void sendEvent(in NfcEvent event, in NfcStatus status);
+}
diff --git a/nfc/aidl/android/hardware/nfc/NfcCloseType.aidl b/nfc/aidl/android/hardware/nfc/NfcCloseType.aidl
new file mode 100644
index 0000000..5160532
--- /dev/null
+++ b/nfc/aidl/android/hardware/nfc/NfcCloseType.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.nfc;
+
+/**
+ * Different closing types for NFC HAL.
+ */
+@VintfStability
+@Backing(type="int")
+enum NfcCloseType {
+    /**
+     * Close the NFC controller and free NFC HAL resources.
+     */
+    DISABLE = 0,
+
+    /**
+     * Switch the NFC controller operation mode and free NFC HAL resources.
+     * Enable NFC functionality for off host card emulation usecases in
+     * device(host) power off(switched off) state, if the device
+     * supports power off use cases. If the device doesn't support power
+     * off use cases, this call should be same as DISABLE.
+     */
+    HOST_SWITCHED_OFF = 1,
+}
diff --git a/nfc/aidl/android/hardware/nfc/NfcConfig.aidl b/nfc/aidl/android/hardware/nfc/NfcConfig.aidl
new file mode 100644
index 0000000..1b4fcfb
--- /dev/null
+++ b/nfc/aidl/android/hardware/nfc/NfcConfig.aidl
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.nfc;
+
+import android.hardware.nfc.PresenceCheckAlgorithm;
+import android.hardware.nfc.ProtocolDiscoveryConfig;
+
+/**
+ * Define Nfc related configurations based on:
+ * NFC Controller Interface (NCI) Technical Specification
+ * https://nfc-forum.org/our-work/specification-releases/
+ */
+@VintfStability
+parcelable NfcConfig {
+    /**
+     * If true, NFCC is using bail out mode for either Type A or Type B poll
+     * based on: Nfc-Forum Activity Technical Specification
+     * https://nfc-forum.org/our-work/specification-releases/
+     */
+    boolean nfaPollBailOutMode;
+    PresenceCheckAlgorithm presenceCheckAlgorithm;
+    ProtocolDiscoveryConfig nfaProprietaryCfg;
+    /**
+     * Default off-host route. 0x00 if there aren't any. Refer to NCI spec.
+     */
+    byte defaultOffHostRoute;
+    /**
+     * Default off-host route for Felica. 0x00 if there aren't any. Refer to
+     * NCI spec.
+     */
+    byte defaultOffHostRouteFelica;
+    /**
+     * Default system code route. 0x00 if there aren't any. Refer NCI spec.
+     */
+    byte defaultSystemCodeRoute;
+    /**
+     * Default power state for system code route. 0x00 if there aren't any.
+     * Refer to NCI spec.
+     */
+    byte defaultSystemCodePowerState;
+    /**
+     * Default route for all remaining protocols and technology which haven't
+     * been configured.
+     * Device Host(0x00) is the default. Refer to NCI spec.
+     *
+     */
+    byte defaultRoute;
+    /**
+     * Pipe ID for eSE. 0x00 if there aren't any.
+     */
+    byte offHostESEPipeId;
+    /**
+     * Pipe ID for UICC. 0x00 if there aren't any.
+     */
+    byte offHostSIMPipeId;
+    /**
+     * Extended APDU length for ISO_DEP. If not supported default length is 261
+     */
+    int maxIsoDepTransceiveLength;
+    /**
+     * list of allowed host ids, as per ETSI TS 102 622
+     * https://www.etsi.org/
+     */
+    byte[] hostAllowlist;
+    /**
+     * NFCEE ID for offhost UICC & eSE secure element.
+     * 0x00 if there aren't any. Refer to NCI spec.
+     */
+    byte[] offHostRouteUicc;
+    byte[] offHostRouteEse;
+    /**
+     * Default IsoDep route. 0x00 if there aren't any. Refer to NCI spec.
+     */
+    byte defaultIsoDepRoute;
+}
diff --git a/nfc/aidl/android/hardware/nfc/NfcEvent.aidl b/nfc/aidl/android/hardware/nfc/NfcEvent.aidl
new file mode 100644
index 0000000..a78b1cd
--- /dev/null
+++ b/nfc/aidl/android/hardware/nfc/NfcEvent.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.nfc;
+
+/**
+ * Nfc event to notify nfc status change.
+ */
+@VintfStability
+@Backing(type="int")
+enum NfcEvent {
+    /**
+     * Open complete event to notify upper layer when NFC HAL and NFCC
+     * initialization complete.
+     */
+    OPEN_CPLT = 0,
+    /**
+     * Close complete event to notify upper layer when HAL close is done.
+     */
+    CLOSE_CPLT = 1,
+    /**
+     * Post init complete event to notify upper layer when post init operations
+     * are done.
+     */
+    POST_INIT_CPLT = 2,
+    /**
+     * Pre-discover complete event to notify upper layer when pre-discover
+     * operations are done.
+     */
+    PRE_DISCOVER_CPLT = 3,
+    /**
+     * HCI network reset event to notify upplayer when HCI network needs to
+     * be re-initialized in case of an error.
+     */
+    HCI_NETWORK_RESET = 4,
+    /**
+     * Error event to notify upper layer when there's an unknown error.
+     */
+    ERROR = 5,
+}
diff --git a/nfc/aidl/android/hardware/nfc/NfcStatus.aidl b/nfc/aidl/android/hardware/nfc/NfcStatus.aidl
new file mode 100644
index 0000000..a38d370
--- /dev/null
+++ b/nfc/aidl/android/hardware/nfc/NfcStatus.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.nfc;
+
+/**
+ * Used to specify the status of the NfcEvent
+ */
+@VintfStability
+@Backing(type="int")
+enum NfcStatus {
+    /**
+     * Default status when NfcEvent with status OK.
+     */
+    OK = 0,
+    /**
+     * Generic error.
+     */
+    FAILED = 1,
+    /**
+     * Transport error.
+     */
+    ERR_TRANSPORT = 2,
+    /**
+     * Command timeout error.
+     */
+    ERR_CMD_TIMEOUT = 3,
+    /**
+     * Refused error when command is rejected.
+     */
+    REFUSED = 4,
+}
diff --git a/nfc/aidl/android/hardware/nfc/PresenceCheckAlgorithm.aidl b/nfc/aidl/android/hardware/nfc/PresenceCheckAlgorithm.aidl
new file mode 100644
index 0000000..20e7bff
--- /dev/null
+++ b/nfc/aidl/android/hardware/nfc/PresenceCheckAlgorithm.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.nfc;
+
+/*
+ * Presence Check Algorithm as defined in ISO/IEC 14443-4:
+ * https://www.iso.org/standard/73599.html
+ */
+@VintfStability
+@Backing(type="byte")
+enum PresenceCheckAlgorithm {
+    /**
+     * Let the stack select an algorithm
+     */
+    DEFAULT = 0,
+    /**
+     * ISO-DEP protocol's empty I-block
+     */
+    I_BLOCK = 1,
+    /**
+     * Type - 4 tag protocol iso-dep nak presence check command is sent waiting for
+     * response and notification.
+     */
+    ISO_DEP_NAK = 2,
+}
diff --git a/nfc/aidl/android/hardware/nfc/ProtocolDiscoveryConfig.aidl b/nfc/aidl/android/hardware/nfc/ProtocolDiscoveryConfig.aidl
new file mode 100644
index 0000000..f8e3228
--- /dev/null
+++ b/nfc/aidl/android/hardware/nfc/ProtocolDiscoveryConfig.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.nfc;
+
+/**
+ * Vendor Specific Proprietary Protocol & Discovery Configuration.
+ * Set to 0xFF if not supported.
+ * discovery* fields map to "RF Technology and Mode" in NCI Spec
+ * protocol* fields map to "RF protocols" in NCI Spec
+ */
+@VintfStability
+parcelable ProtocolDiscoveryConfig {
+    byte protocol18092Active;
+    byte protocolBPrime;
+    byte protocolDual;
+    byte protocol15693;
+    byte protocolKovio;
+    byte protocolMifare;
+    byte discoveryPollKovio;
+    byte discoveryPollBPrime;
+    byte discoveryListenBPrime;
+}
diff --git a/nfc/aidl/default/Android.bp b/nfc/aidl/default/Android.bp
new file mode 100644
index 0000000..6daebe5
--- /dev/null
+++ b/nfc/aidl/default/Android.bp
@@ -0,0 +1,32 @@
+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.nfc-service.example",
+    relative_install_path: "hw",
+    init_rc: ["nfc-service-example.rc"],
+    vintf_fragments: ["nfc-service-example.xml"],
+    vendor: true,
+    cflags: [
+        "-Wall",
+        "-Wextra",
+    ],
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "libutils",
+        "libbinder_ndk",
+        "android.hardware.nfc-V1-ndk",
+    ],
+    srcs: [
+        "main.cpp",
+        "Nfc.cpp",
+        "Vendor_hal_api.cpp",
+    ],
+}
diff --git a/nfc/aidl/default/Nfc.cpp b/nfc/aidl/default/Nfc.cpp
new file mode 100644
index 0000000..4685b59
--- /dev/null
+++ b/nfc/aidl/default/Nfc.cpp
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Nfc.h"
+
+#include <android-base/logging.h>
+
+#include "Vendor_hal_api.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace nfc {
+
+std::shared_ptr<INfcClientCallback> Nfc::mCallback = nullptr;
+AIBinder_DeathRecipient* clientDeathRecipient = nullptr;
+
+void OnDeath(void* cookie) {
+    if (Nfc::mCallback != nullptr && !AIBinder_isAlive(Nfc::mCallback->asBinder().get())) {
+        LOG(INFO) << __func__ << " Nfc service has died";
+        Nfc* nfc = static_cast<Nfc*>(cookie);
+        nfc->close(NfcCloseType::DISABLE);
+    }
+}
+
+::ndk::ScopedAStatus Nfc::open(const std::shared_ptr<INfcClientCallback>& clientCallback) {
+    LOG(INFO) << "open";
+    if (clientCallback == nullptr) {
+        LOG(INFO) << "Nfc::open null callback";
+        return ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(NfcStatus::FAILED));
+    }
+    Nfc::mCallback = clientCallback;
+
+    clientDeathRecipient = AIBinder_DeathRecipient_new(OnDeath);
+    auto linkRet = AIBinder_linkToDeath(clientCallback->asBinder().get(), clientDeathRecipient,
+                                        this /* cookie */);
+    if (linkRet != STATUS_OK) {
+        LOG(ERROR) << __func__ << ": linkToDeath failed: " << linkRet;
+        // Just ignore the error.
+    }
+
+    int ret = Vendor_hal_open(eventCallback, dataCallback);
+    return ret == 0 ? ndk::ScopedAStatus::ok()
+                    : ndk::ScopedAStatus::fromServiceSpecificError(
+                              static_cast<int32_t>(NfcStatus::FAILED));
+}
+
+::ndk::ScopedAStatus Nfc::close(NfcCloseType type) {
+    LOG(INFO) << "close";
+    if (Nfc::mCallback == nullptr) {
+        LOG(ERROR) << __func__ << "mCallback null";
+        return ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(NfcStatus::FAILED));
+    }
+    int ret = 0;
+    if (type == NfcCloseType::HOST_SWITCHED_OFF) {
+        ret = Vendor_hal_close_off();
+    } else {
+        ret = Vendor_hal_close();
+    }
+    Nfc::mCallback = nullptr;
+    AIBinder_DeathRecipient_delete(clientDeathRecipient);
+    clientDeathRecipient = nullptr;
+    return ret == 0 ? ndk::ScopedAStatus::ok()
+                    : ndk::ScopedAStatus::fromServiceSpecificError(
+                              static_cast<int32_t>(NfcStatus::FAILED));
+}
+
+::ndk::ScopedAStatus Nfc::coreInitialized() {
+    LOG(INFO) << "coreInitialized";
+    if (Nfc::mCallback == nullptr) {
+        LOG(ERROR) << __func__ << "mCallback null";
+        return ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(NfcStatus::FAILED));
+    }
+    int ret = Vendor_hal_core_initialized();
+
+    return ret == 0 ? ndk::ScopedAStatus::ok()
+                    : ndk::ScopedAStatus::fromServiceSpecificError(
+                              static_cast<int32_t>(NfcStatus::FAILED));
+}
+
+::ndk::ScopedAStatus Nfc::factoryReset() {
+    LOG(INFO) << "factoryReset";
+    Vendor_hal_factoryReset();
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Nfc::getConfig(NfcConfig* _aidl_return) {
+    LOG(INFO) << "getConfig";
+    NfcConfig nfcVendorConfig;
+    Vendor_hal_getConfig(nfcVendorConfig);
+
+    *_aidl_return = nfcVendorConfig;
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Nfc::powerCycle() {
+    LOG(INFO) << "powerCycle";
+    if (Nfc::mCallback == nullptr) {
+        LOG(ERROR) << __func__ << "mCallback null";
+        return ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(NfcStatus::FAILED));
+    }
+    return Vendor_hal_power_cycle() ? ndk::ScopedAStatus::fromServiceSpecificError(
+                                              static_cast<int32_t>(NfcStatus::FAILED))
+                                    : ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Nfc::preDiscover() {
+    LOG(INFO) << "preDiscover";
+    if (Nfc::mCallback == nullptr) {
+        LOG(ERROR) << __func__ << "mCallback null";
+        return ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(NfcStatus::FAILED));
+    }
+    return Vendor_hal_pre_discover() ? ndk::ScopedAStatus::fromServiceSpecificError(
+                                               static_cast<int32_t>(NfcStatus::FAILED))
+                                     : ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Nfc::write(const std::vector<uint8_t>& data, int32_t* _aidl_return) {
+    LOG(INFO) << "write";
+    if (Nfc::mCallback == nullptr) {
+        LOG(ERROR) << __func__ << "mCallback null";
+        return ndk::ScopedAStatus::fromServiceSpecificError(
+                static_cast<int32_t>(NfcStatus::FAILED));
+    }
+    *_aidl_return = Vendor_hal_write(data.size(), &data[0]);
+    return ndk::ScopedAStatus::ok();
+}
+::ndk::ScopedAStatus Nfc::setEnableVerboseLogging(bool enable) {
+    LOG(INFO) << "setVerboseLogging";
+    Vendor_hal_setVerboseLogging(enable);
+    return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Nfc::isVerboseLoggingEnabled(bool* _aidl_return) {
+    *_aidl_return = Vendor_hal_getVerboseLogging();
+    return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace nfc
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/nfc/aidl/default/Nfc.h b/nfc/aidl/default/Nfc.h
new file mode 100644
index 0000000..1b14534
--- /dev/null
+++ b/nfc/aidl/default/Nfc.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/nfc/BnNfc.h>
+#include <aidl/android/hardware/nfc/INfcClientCallback.h>
+#include <android-base/logging.h>
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace nfc {
+
+using ::aidl::android::hardware::nfc::NfcCloseType;
+using ::aidl::android::hardware::nfc::NfcConfig;
+using ::aidl::android::hardware::nfc::NfcStatus;
+
+// Default implementation that reports no support NFC.
+struct Nfc : public BnNfc {
+  public:
+    Nfc() = default;
+
+    ::ndk::ScopedAStatus open(const std::shared_ptr<INfcClientCallback>& clientCallback) override;
+    ::ndk::ScopedAStatus close(NfcCloseType type) override;
+    ::ndk::ScopedAStatus coreInitialized() override;
+    ::ndk::ScopedAStatus factoryReset() override;
+    ::ndk::ScopedAStatus getConfig(NfcConfig* _aidl_return) override;
+    ::ndk::ScopedAStatus powerCycle() override;
+    ::ndk::ScopedAStatus preDiscover() override;
+    ::ndk::ScopedAStatus write(const std::vector<uint8_t>& data, int32_t* _aidl_return) override;
+    ::ndk::ScopedAStatus setEnableVerboseLogging(bool enable) override;
+    ::ndk::ScopedAStatus isVerboseLoggingEnabled(bool* _aidl_return) override;
+
+    static void eventCallback(uint8_t event, uint8_t status) {
+        if (mCallback != nullptr) {
+            auto ret = mCallback->sendEvent((NfcEvent)event, (NfcStatus)status);
+            if (!ret.isOk()) {
+                LOG(ERROR) << "Failed to send event!";
+            }
+        }
+    }
+
+    static void dataCallback(uint16_t data_len, uint8_t* p_data) {
+        std::vector<uint8_t> data(p_data, p_data + data_len);
+        if (mCallback != nullptr) {
+            auto ret = mCallback->sendData(data);
+            if (!ret.isOk()) {
+                LOG(ERROR) << "Failed to send data!";
+            }
+        }
+    }
+
+    static std::shared_ptr<INfcClientCallback> mCallback;
+};
+
+}  // namespace nfc
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/nfc/aidl/default/Vendor_hal_api.cpp b/nfc/aidl/default/Vendor_hal_api.cpp
new file mode 100644
index 0000000..66a2ebc
--- /dev/null
+++ b/nfc/aidl/default/Vendor_hal_api.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/properties.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <string.h>
+
+#include "Vendor_hal_api.h"
+
+bool logging = false;
+
+int Vendor_hal_open(nfc_stack_callback_t* p_cback, nfc_stack_data_callback_t* p_data_cback) {
+    (void)p_cback;
+    (void)p_data_cback;
+    // nothing to open in this example
+    return -1;
+}
+
+int Vendor_hal_write(uint16_t data_len, const uint8_t* p_data) {
+    (void)data_len;
+    (void)p_data;
+    return -1;
+}
+
+int Vendor_hal_core_initialized() {
+    return -1;
+}
+
+int Vendor_hal_pre_discover() {
+    return -1;
+}
+
+int Vendor_hal_close() {
+    return -1;
+}
+
+int Vendor_hal_close_off() {
+    return -1;
+}
+
+int Vendor_hal_power_cycle() {
+    return -1;
+}
+
+void Vendor_hal_factoryReset() {}
+
+void Vendor_hal_getConfig(NfcConfig& config) {
+    (void)config;
+}
+
+void Vendor_hal_setVerboseLogging(bool enable) {
+    logging = enable;
+}
+
+bool Vendor_hal_getVerboseLogging() {
+    return logging;
+}
diff --git a/nfc/aidl/default/Vendor_hal_api.h b/nfc/aidl/default/Vendor_hal_api.h
new file mode 100644
index 0000000..595c2dd
--- /dev/null
+++ b/nfc/aidl/default/Vendor_hal_api.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <aidl/android/hardware/nfc/INfc.h>
+#include <aidl/android/hardware/nfc/NfcConfig.h>
+#include <aidl/android/hardware/nfc/NfcEvent.h>
+#include <aidl/android/hardware/nfc/NfcStatus.h>
+#include <aidl/android/hardware/nfc/PresenceCheckAlgorithm.h>
+#include <aidl/android/hardware/nfc/ProtocolDiscoveryConfig.h>
+#include "hardware_nfc.h"
+
+using aidl::android::hardware::nfc::NfcConfig;
+using aidl::android::hardware::nfc::NfcEvent;
+using aidl::android::hardware::nfc::NfcStatus;
+using aidl::android::hardware::nfc::PresenceCheckAlgorithm;
+using aidl::android::hardware::nfc::ProtocolDiscoveryConfig;
+
+int Vendor_hal_open(nfc_stack_callback_t* p_cback, nfc_stack_data_callback_t* p_data_cback);
+int Vendor_hal_write(uint16_t data_len, const uint8_t* p_data);
+
+int Vendor_hal_core_initialized();
+
+int Vendor_hal_pre_discover();
+
+int Vendor_hal_close();
+
+int Vendor_hal_close_off();
+
+int Vendor_hal_power_cycle();
+
+void Vendor_hal_factoryReset();
+
+void Vendor_hal_getConfig(NfcConfig& config);
+
+void Vendor_hal_setVerboseLogging(bool enable);
+
+bool Vendor_hal_getVerboseLogging();
diff --git a/nfc/aidl/default/hardware_nfc.h b/nfc/aidl/default/hardware_nfc.h
new file mode 100644
index 0000000..0f856c5
--- /dev/null
+++ b/nfc/aidl/default/hardware_nfc.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+typedef uint8_t nfc_event_t;
+typedef uint8_t nfc_status_t;
+
+/*
+ * The callback passed in from the NFC stack that the HAL
+ * can use to pass events back to the stack.
+ */
+typedef void(nfc_stack_callback_t)(nfc_event_t event, nfc_status_t event_status);
+
+/*
+ * The callback passed in from the NFC stack that the HAL
+ * can use to pass incomming data to the stack.
+ */
+typedef void(nfc_stack_data_callback_t)(uint16_t data_len, uint8_t* p_data);
diff --git a/nfc/aidl/default/main.cpp b/nfc/aidl/default/main.cpp
new file mode 100644
index 0000000..0cc51e7
--- /dev/null
+++ b/nfc/aidl/default/main.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+#include "Nfc.h"
+using ::aidl::android::hardware::nfc::Nfc;
+
+int main() {
+    LOG(INFO) << "NFC HAL starting up";
+    if (!ABinderProcess_setThreadPoolMaxThreadCount(1)) {
+        LOG(INFO) << "failed to set thread pool max thread count";
+        return 1;
+    }
+    std::shared_ptr<Nfc> nfc_service = ndk::SharedRefBase::make<Nfc>();
+
+    const std::string instance = std::string() + Nfc::descriptor + "/default";
+    binder_status_t status =
+            AServiceManager_addService(nfc_service->asBinder().get(), instance.c_str());
+    CHECK(status == STATUS_OK);
+    ABinderProcess_joinThreadPool();
+    return 0;
+}
diff --git a/nfc/aidl/default/nfc-service-example.rc b/nfc/aidl/default/nfc-service-example.rc
new file mode 100644
index 0000000..7d7052e
--- /dev/null
+++ b/nfc/aidl/default/nfc-service-example.rc
@@ -0,0 +1,4 @@
+service nfc_hal_service /vendor/bin/hw/android.hardware.nfc-service.st
+    class hal
+    user nfc
+    group nfc
diff --git a/nfc/aidl/default/nfc-service-example.xml b/nfc/aidl/default/nfc-service-example.xml
new file mode 100644
index 0000000..70fed20
--- /dev/null
+++ b/nfc/aidl/default/nfc-service-example.xml
@@ -0,0 +1,6 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.nfc</name>
+        <fqname>INfc/default</fqname>
+    </hal>
+</manifest>
diff --git a/nfc/aidl/vts/functional/Android.bp b/nfc/aidl/vts/functional/Android.bp
new file mode 100644
index 0000000..99eecd0
--- /dev/null
+++ b/nfc/aidl/vts/functional/Android.bp
@@ -0,0 +1,46 @@
+//
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+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: "VtsAidlHalNfcTargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    srcs: [
+        "VtsAidlHalNfcTargetTest.cpp",
+    ],
+    shared_libs: [
+        "libbinder",
+        "libbinder_ndk",
+    ],
+    static_libs: [
+        "android.hardware.nfc-V1-ndk",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
diff --git a/nfc/aidl/vts/functional/VtsAidlHalNfcTargetTest.cpp b/nfc/aidl/vts/functional/VtsAidlHalNfcTargetTest.cpp
new file mode 100644
index 0000000..977b25c
--- /dev/null
+++ b/nfc/aidl/vts/functional/VtsAidlHalNfcTargetTest.cpp
@@ -0,0 +1,458 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "nfc_aidl_hal_test"
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/nfc/BnNfc.h>
+#include <aidl/android/hardware/nfc/BnNfcClientCallback.h>
+#include <aidl/android/hardware/nfc/INfc.h>
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <android/binder_auto_utils.h>
+#include <android/binder_enums.h>
+#include <android/binder_interface_utils.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+#include <chrono>
+#include <future>
+
+using aidl::android::hardware::nfc::INfc;
+using aidl::android::hardware::nfc::INfcClientCallback;
+using aidl::android::hardware::nfc::NfcCloseType;
+using aidl::android::hardware::nfc::NfcConfig;
+using aidl::android::hardware::nfc::NfcEvent;
+using aidl::android::hardware::nfc::NfcStatus;
+using aidl::android::hardware::nfc::PresenceCheckAlgorithm;
+
+using android::getAidlHalInstanceNames;
+using android::PrintInstanceNameToString;
+using android::base::StringPrintf;
+using ndk::enum_range;
+using ndk::ScopedAStatus;
+using ndk::SharedRefBase;
+using ndk::SpAIBinder;
+
+constexpr static int kCallbackTimeoutMs = 10000;
+
+// 261 bytes is the default and minimum transceive length
+constexpr unsigned int MIN_ISO_DEP_TRANSCEIVE_LENGTH = 261;
+
+// Range of valid off host route ids
+constexpr uint8_t MIN_OFFHOST_ROUTE_ID = 0x01;
+constexpr uint8_t MAX_OFFHOST_ROUTE_ID = 0xFE;
+
+class NfcClientCallback : public aidl::android::hardware::nfc::BnNfcClientCallback {
+  public:
+    NfcClientCallback(const std::function<void(NfcEvent, NfcStatus)>& on_hal_event_cb,
+                      const std::function<void(const std::vector<uint8_t>&)>& on_nci_data_cb)
+        : on_nci_data_cb_(on_nci_data_cb), on_hal_event_cb_(on_hal_event_cb) {}
+    virtual ~NfcClientCallback() = default;
+
+    ::ndk::ScopedAStatus sendEvent(NfcEvent event, NfcStatus event_status) override {
+        on_hal_event_cb_(event, event_status);
+        return ::ndk::ScopedAStatus::ok();
+    };
+    ::ndk::ScopedAStatus sendData(const std::vector<uint8_t>& data) override {
+        on_nci_data_cb_(data);
+        return ::ndk::ScopedAStatus::ok();
+    };
+
+  private:
+    std::function<void(const std::vector<uint8_t>&)> on_nci_data_cb_;
+    std::function<void(NfcEvent, NfcStatus)> on_hal_event_cb_;
+};
+
+class NfcAidl : public testing::TestWithParam<std::string> {
+  public:
+    void SetUp() override {
+        SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str()));
+        infc_ = INfc::fromBinder(binder);
+        ASSERT_NE(infc_, nullptr);
+    }
+    std::shared_ptr<INfc> infc_;
+};
+
+/*
+ * OpenAndCloseForDisable:
+ * Makes an open call, waits for NfcEvent::OPEN_CPLT
+ * Immediately calls close(NfcCloseType::DISABLE) and
+ * waits for NfcEvent::CLOSE_CPLT
+ *
+ */
+TEST_P(NfcAidl, OpenAndCloseForDisable) {
+    std::promise<void> open_cb_promise;
+    std::promise<void> close_cb_promise;
+    auto open_cb_future = open_cb_promise.get_future();
+    auto close_cb_future = close_cb_promise.get_future();
+    std::shared_ptr<INfcClientCallback> mCallback = ::ndk::SharedRefBase::make<NfcClientCallback>(
+            [&open_cb_promise, &close_cb_promise](auto event, auto status) {
+                EXPECT_EQ(status, NfcStatus::OK);
+                LOG(INFO) << StringPrintf("%s,%d ", __func__, event);
+                if (event == NfcEvent::OPEN_CPLT) open_cb_promise.set_value();
+                if (event == NfcEvent::CLOSE_CPLT) close_cb_promise.set_value();
+            },
+            [](auto) {});
+    std::chrono::milliseconds timeout{kCallbackTimeoutMs};
+    // Open and wait for OPEN_CPLT
+    LOG(INFO) << "open";
+    EXPECT_TRUE(infc_->open(mCallback).isOk());
+    EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
+    // Close and wait for CLOSE_CPLT
+    LOG(INFO) << "close DISABLE";
+    EXPECT_TRUE(infc_->close(NfcCloseType::DISABLE).isOk());
+    LOG(INFO) << "wait for close";
+    EXPECT_EQ(close_cb_future.wait_for(timeout), std::future_status::ready);
+}
+
+/*
+ * OpenAndCloseForHostSwitchedOff:
+ * Makes an open call, waits for NfcEvent::OPEN_CPLT
+ * Immediately calls close(NfcCloseType::HOST_SWITCHED_OFF) and
+ * waits for NfcEvent::CLOSE_CPLT
+ *
+ */
+TEST_P(NfcAidl, OpenAndCloseForHostSwitchedOff) {
+    std::promise<void> open_cb_promise;
+    std::promise<void> close_cb_promise;
+    auto open_cb_future = open_cb_promise.get_future();
+    auto close_cb_future = close_cb_promise.get_future();
+    std::shared_ptr<INfcClientCallback> mCallback = ::ndk::SharedRefBase::make<NfcClientCallback>(
+            [&open_cb_promise, &close_cb_promise](auto event, auto status) {
+                EXPECT_EQ(status, NfcStatus::OK);
+                if (event == NfcEvent::OPEN_CPLT) open_cb_promise.set_value();
+                if (event == NfcEvent::CLOSE_CPLT) close_cb_promise.set_value();
+            },
+            [](auto) {});
+    std::chrono::milliseconds timeout{kCallbackTimeoutMs};
+    // Open and wait for OPEN_CPLT
+    LOG(INFO) << "open";
+    EXPECT_TRUE(infc_->open(mCallback).isOk());
+    EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
+
+    // Close and wait for CLOSE_CPLT
+    LOG(INFO) << "close HOST_SWITCHED_OFF";
+    EXPECT_TRUE(infc_->close(NfcCloseType::HOST_SWITCHED_OFF).isOk());
+    EXPECT_EQ(close_cb_future.wait_for(timeout), std::future_status::ready);
+}
+
+/*
+ * OpenAfterOpen:
+ * Calls open() multiple times
+ * Checks status
+ */
+TEST_P(NfcAidl, OpenAfterOpen) {
+    int open_count = 0;
+    std::promise<void> open_cb_promise;
+    std::promise<void> open2_cb_promise;
+    auto open_cb_future = open_cb_promise.get_future();
+    auto open2_cb_future = open2_cb_promise.get_future();
+    std::shared_ptr<INfcClientCallback> mCallback = ::ndk::SharedRefBase::make<NfcClientCallback>(
+            [&open_cb_promise, &open2_cb_promise, &open_count](auto event, auto status) {
+                EXPECT_EQ(status, NfcStatus::OK);
+                if (event == NfcEvent::OPEN_CPLT) {
+                    open_count == 0 ? open_cb_promise.set_value() : open2_cb_promise.set_value();
+                    open_count++;
+                }
+            },
+            [](auto) {});
+
+    std::chrono::milliseconds timeout{kCallbackTimeoutMs};
+    // Open and wait for OPEN_CPLT
+    LOG(INFO) << "open";
+    EXPECT_TRUE(infc_->open(mCallback).isOk());
+    EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
+
+    // Open again and wait for OPEN_CPLT
+    LOG(INFO) << "open again";
+    EXPECT_TRUE(infc_->open(mCallback).isOk());
+    EXPECT_EQ(open2_cb_future.wait_for(timeout), std::future_status::ready);
+}
+
+/*
+ * CloseAfterClose:
+ * Calls close() multiple times
+ * Checks status
+ */
+TEST_P(NfcAidl, CloseAfterClose) {
+    std::promise<void> open_cb_promise;
+    std::promise<void> close_cb_promise;
+    auto open_cb_future = open_cb_promise.get_future();
+    auto close_cb_future = close_cb_promise.get_future();
+    std::shared_ptr<INfcClientCallback> mCallback = ::ndk::SharedRefBase::make<NfcClientCallback>(
+            [&open_cb_promise, &close_cb_promise](auto event, auto status) {
+                EXPECT_EQ(status, NfcStatus::OK);
+                if (event == NfcEvent::OPEN_CPLT) open_cb_promise.set_value();
+                if (event == NfcEvent::CLOSE_CPLT) close_cb_promise.set_value();
+            },
+            [](auto) {});
+    std::chrono::milliseconds timeout{kCallbackTimeoutMs};
+    // Open and wait for OPEN_CPLT
+    LOG(INFO) << "open";
+    EXPECT_TRUE(infc_->open(mCallback).isOk());
+    EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
+
+    // Close and wait for CLOSE_CPLT
+    LOG(INFO) << "close";
+    EXPECT_TRUE(infc_->close(NfcCloseType::DISABLE).isOk());
+    EXPECT_EQ(close_cb_future.wait_for(timeout), std::future_status::ready);
+    // Close again should fail.
+    LOG(INFO) << "close again";
+    EXPECT_TRUE(!(infc_->close(NfcCloseType::DISABLE).isOk()));
+}
+
+/*
+ * PowerCycleAfterOpen:
+ * Calls powerCycle() after open
+ * Waits for NfcEvent.OPEN_CPLT
+ * Checks status
+ */
+TEST_P(NfcAidl, PowerCycleAfterOpen) {
+    int open_cplt_count = 0;
+    std::promise<void> open_cb_promise;
+    std::promise<void> power_cycle_cb_promise;
+    std::promise<void> close_cb_promise;
+    auto open_cb_future = open_cb_promise.get_future();
+    auto power_cycle_cb_future = power_cycle_cb_promise.get_future();
+    auto close_cb_future = close_cb_promise.get_future();
+    std::shared_ptr<INfcClientCallback> mCallback = ::ndk::SharedRefBase::make<NfcClientCallback>(
+            [&open_cb_promise, &close_cb_promise, &power_cycle_cb_promise, &open_cplt_count](
+                    auto event, auto status) {
+                EXPECT_EQ(status, NfcStatus::OK);
+                if (event == NfcEvent::OPEN_CPLT) {
+                    if (open_cplt_count == 0) {
+                        open_cplt_count++;
+                        open_cb_promise.set_value();
+                    } else {
+                        power_cycle_cb_promise.set_value();
+                    }
+                }
+                if (event == NfcEvent::CLOSE_CPLT) close_cb_promise.set_value();
+            },
+            [](auto) {});
+    std::chrono::milliseconds timeout{kCallbackTimeoutMs};
+    // Open and wait for OPEN_CPLT
+    LOG(INFO) << "open";
+    EXPECT_TRUE(infc_->open(mCallback).isOk());
+    EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
+
+    // PowerCycle and wait for OPEN_CPLT
+    LOG(INFO) << "PowerCycle";
+    EXPECT_TRUE(infc_->powerCycle().isOk());
+    EXPECT_EQ(power_cycle_cb_future.wait_for(timeout), std::future_status::ready);
+
+    // Close and wait for CLOSE_CPLT
+    LOG(INFO) << "close";
+    EXPECT_TRUE(infc_->close(NfcCloseType::DISABLE).isOk());
+    EXPECT_EQ(close_cb_future.wait_for(timeout), std::future_status::ready);
+}
+
+/*
+ * PowerCycleAfterClose:
+ * Calls powerCycle() after close
+ * PowerCycle should fail immediately
+ */
+TEST_P(NfcAidl, PowerCycleAfterClose) {
+    std::promise<void> open_cb_promise;
+    std::promise<void> close_cb_promise;
+    auto open_cb_future = open_cb_promise.get_future();
+    auto close_cb_future = close_cb_promise.get_future();
+    std::shared_ptr<INfcClientCallback> mCallback = ::ndk::SharedRefBase::make<NfcClientCallback>(
+            [&open_cb_promise, &close_cb_promise](auto event, auto status) {
+                EXPECT_EQ(status, NfcStatus::OK);
+                if (event == NfcEvent::OPEN_CPLT) open_cb_promise.set_value();
+                if (event == NfcEvent::CLOSE_CPLT) close_cb_promise.set_value();
+            },
+            [](auto) {});
+    std::chrono::milliseconds timeout{kCallbackTimeoutMs};
+    // Open and wait for OPEN_CPLT
+    LOG(INFO) << "open";
+    EXPECT_TRUE(infc_->open(mCallback).isOk());
+    EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
+
+    // Close and wait for CLOSE_CPLT
+    LOG(INFO) << "close";
+    EXPECT_TRUE(infc_->close(NfcCloseType::DISABLE).isOk());
+    EXPECT_EQ(close_cb_future.wait_for(timeout), std::future_status::ready);
+
+    // PowerCycle should fail
+    LOG(INFO) << "PowerCycle";
+    EXPECT_TRUE(!(infc_->powerCycle().isOk()));
+}
+
+/*
+ * CoreInitializedAfterOpen:
+ * Calls coreInitialized() after open
+ * Waits for NfcEvent.POST_INIT_CPLT
+ */
+TEST_P(NfcAidl, CoreInitializedAfterOpen) {
+    std::promise<void> open_cb_promise;
+    std::promise<void> core_init_cb_promise;
+    std::promise<void> close_cb_promise;
+    auto open_cb_future = open_cb_promise.get_future();
+    auto core_init_cb_future = core_init_cb_promise.get_future();
+    auto close_cb_future = close_cb_promise.get_future();
+    std::shared_ptr<INfcClientCallback> mCallback = ::ndk::SharedRefBase::make<NfcClientCallback>(
+            [&open_cb_promise, &close_cb_promise, &core_init_cb_promise](auto event, auto status) {
+                EXPECT_EQ(status, NfcStatus::OK);
+                if (event == NfcEvent::OPEN_CPLT) open_cb_promise.set_value();
+                if (event == NfcEvent::POST_INIT_CPLT) core_init_cb_promise.set_value();
+                if (event == NfcEvent::CLOSE_CPLT) close_cb_promise.set_value();
+            },
+            [](auto) {});
+    std::chrono::milliseconds timeout{kCallbackTimeoutMs};
+    // Open and wait for OPEN_CPLT
+    LOG(INFO) << "open";
+    EXPECT_TRUE(infc_->open(mCallback).isOk());
+    EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
+
+    // CoreInitialized and wait for POST_INIT_CPLT
+    LOG(INFO) << "coreInitialized";
+    EXPECT_TRUE(infc_->coreInitialized().isOk());
+    EXPECT_EQ(core_init_cb_future.wait_for(timeout), std::future_status::ready);
+
+    // Close and wait for CLOSE_CPLT
+    LOG(INFO) << "close";
+    EXPECT_TRUE(infc_->close(NfcCloseType::DISABLE).isOk());
+    EXPECT_EQ(close_cb_future.wait_for(timeout), std::future_status::ready);
+}
+
+/*
+ * CoreInitializedAfterClose:
+ * Calls coreInitialized() after close
+ * coreInitialized() should fail immediately
+ */
+TEST_P(NfcAidl, CoreInitializedAfterClose) {
+    std::promise<void> open_cb_promise;
+    std::promise<void> close_cb_promise;
+    auto open_cb_future = open_cb_promise.get_future();
+    auto close_cb_future = close_cb_promise.get_future();
+    std::shared_ptr<INfcClientCallback> mCallback = ::ndk::SharedRefBase::make<NfcClientCallback>(
+            [&open_cb_promise, &close_cb_promise](auto event, auto status) {
+                EXPECT_EQ(status, NfcStatus::OK);
+                if (event == NfcEvent::OPEN_CPLT) open_cb_promise.set_value();
+                if (event == NfcEvent::CLOSE_CPLT) close_cb_promise.set_value();
+            },
+            [](auto) {});
+    std::chrono::milliseconds timeout{kCallbackTimeoutMs};
+    // Open and wait for OPEN_CPLT
+    LOG(INFO) << "open";
+    EXPECT_TRUE(infc_->open(mCallback).isOk());
+    EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
+
+    // Close and wait for CLOSE_CPLT
+    LOG(INFO) << "close";
+    EXPECT_TRUE(infc_->close(NfcCloseType::DISABLE).isOk());
+    EXPECT_EQ(close_cb_future.wait_for(timeout), std::future_status::ready);
+
+    // coreInitialized should fail
+    LOG(INFO) << "CoreInitialized";
+    EXPECT_TRUE(!(infc_->coreInitialized().isOk()));
+}
+
+/*
+ * PreDiscoverAfterClose:
+ * Call preDiscover() after close
+ * preDiscover() should fail immediately
+ */
+TEST_P(NfcAidl, PreDiscoverAfterClose) {
+    std::promise<void> open_cb_promise;
+    std::promise<void> close_cb_promise;
+    auto open_cb_future = open_cb_promise.get_future();
+    auto close_cb_future = close_cb_promise.get_future();
+    std::shared_ptr<INfcClientCallback> mCallback = ::ndk::SharedRefBase::make<NfcClientCallback>(
+            [&open_cb_promise, &close_cb_promise](auto event, auto status) {
+                EXPECT_EQ(status, NfcStatus::OK);
+                if (event == NfcEvent::OPEN_CPLT) open_cb_promise.set_value();
+                if (event == NfcEvent::CLOSE_CPLT) close_cb_promise.set_value();
+            },
+            [](auto) {});
+    std::chrono::milliseconds timeout{kCallbackTimeoutMs};
+    // Open and wait for OPEN_CPLT
+    LOG(INFO) << "open";
+    EXPECT_TRUE(infc_->open(mCallback).isOk());
+    EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
+
+    // Close and wait for CLOSE_CPLT
+    LOG(INFO) << "close";
+    EXPECT_TRUE(infc_->close(NfcCloseType::DISABLE).isOk());
+    EXPECT_EQ(close_cb_future.wait_for(timeout), std::future_status::ready);
+
+    // preDiscover should fail
+    LOG(INFO) << "preDiscover";
+    EXPECT_TRUE(!(infc_->preDiscover().isOk()));
+}
+
+/*
+ * checkGetConfigValues:
+ * Calls getConfig()
+ * checks if fields in NfcConfig are populated correctly
+ */
+TEST_P(NfcAidl, CheckGetConfigValues) {
+    NfcConfig configValue;
+    EXPECT_TRUE(infc_->getConfig(&configValue).isOk());
+    EXPECT_GE(configValue.maxIsoDepTransceiveLength, MIN_ISO_DEP_TRANSCEIVE_LENGTH);
+    LOG(INFO) << StringPrintf("configValue.maxIsoDepTransceiveLength = %x",
+                              configValue.maxIsoDepTransceiveLength);
+    for (auto uicc : configValue.offHostRouteUicc) {
+        LOG(INFO) << StringPrintf("offHostRouteUicc = %x", uicc);
+        EXPECT_GE(uicc, MIN_OFFHOST_ROUTE_ID);
+        EXPECT_LE(uicc, MAX_OFFHOST_ROUTE_ID);
+    }
+    for (auto ese : configValue.offHostRouteEse) {
+        LOG(INFO) << StringPrintf("offHostRouteEse = %x", ese);
+        EXPECT_GE(ese, MIN_OFFHOST_ROUTE_ID);
+        EXPECT_LE(ese, MAX_OFFHOST_ROUTE_ID);
+    }
+    if (configValue.defaultIsoDepRoute != 0) {
+        EXPECT_GE((uint8_t)configValue.defaultIsoDepRoute, MIN_OFFHOST_ROUTE_ID);
+        EXPECT_LE((uint8_t)configValue.defaultIsoDepRoute, MAX_OFFHOST_ROUTE_ID);
+    }
+}
+
+/*
+ * CheckisVerboseLoggingEnabledAfterSetEnableVerboseLogging:
+ * Calls setEnableVerboseLogging()
+ * checks the return value of isVerboseLoggingEnabled
+ */
+TEST_P(NfcAidl, CheckisVerboseLoggingEnabledAfterSetEnableVerboseLogging) {
+    bool enabled = false;
+    EXPECT_TRUE(infc_->setEnableVerboseLogging(true).isOk());
+    EXPECT_TRUE(infc_->isVerboseLoggingEnabled(&enabled).isOk());
+    EXPECT_TRUE(enabled);
+    EXPECT_TRUE(infc_->setEnableVerboseLogging(false).isOk());
+    EXPECT_TRUE(infc_->isVerboseLoggingEnabled(&enabled).isOk());
+    EXPECT_TRUE(!enabled);
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(NfcAidl);
+INSTANTIATE_TEST_SUITE_P(Nfc, NfcAidl,
+                         testing::ValuesIn(::android::getAidlHalInstanceNames(INfc::descriptor)),
+                         ::android::PrintInstanceNameToString);
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    ABinderProcess_startThreadPool();
+    std::system("/system/bin/svc nfc disable"); /* Turn off NFC */
+    sleep(5);
+    int status = RUN_ALL_TESTS();
+    LOG(INFO) << "Test result = " << status;
+    std::system("/system/bin/svc nfc enable"); /* Turn on NFC */
+    sleep(5);
+    return status;
+}
diff --git a/oemlock/1.0/vts/functional/OWNERS b/oemlock/1.0/vts/functional/OWNERS
new file mode 100644
index 0000000..ec8c304
--- /dev/null
+++ b/oemlock/1.0/vts/functional/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 186411
+chengyouho@google.com
+frankwoo@google.com
diff --git a/oemlock/aidl/default/Android.bp b/oemlock/aidl/default/Android.bp
index 84136fe..063199a 100644
--- a/oemlock/aidl/default/Android.bp
+++ b/oemlock/aidl/default/Android.bp
@@ -34,7 +34,7 @@
         "OemLock.cpp",
     ],
     shared_libs: [
-        "android.hardware.oemlock-V1-ndk_platform",
+        "android.hardware.oemlock-V1-ndk",
         "libbase",
         "libbinder_ndk",
     ],
diff --git a/oemlock/aidl/default/service.cpp b/oemlock/aidl/default/service.cpp
index af828a0..9fa7d63 100644
--- a/oemlock/aidl/default/service.cpp
+++ b/oemlock/aidl/default/service.cpp
@@ -28,7 +28,7 @@
 
     const std::string instance = std::string() + OemLock::descriptor + "/default";
     binder_status_t status = AServiceManager_addService(oemlock->asBinder().get(), instance.c_str());
-    CHECK(status == STATUS_OK);
+    CHECK_EQ(status, STATUS_OK);
 
     ABinderProcess_joinThreadPool();
     return -1; // Should never be reached
diff --git a/oemlock/aidl/vts/Android.bp b/oemlock/aidl/vts/Android.bp
index 840d20a..eb999a9 100644
--- a/oemlock/aidl/vts/Android.bp
+++ b/oemlock/aidl/vts/Android.bp
@@ -34,7 +34,7 @@
         "libbinder_ndk",
         "libbase",
     ],
-    static_libs: ["android.hardware.oemlock-V1-ndk_platform"],
+    static_libs: ["android.hardware.oemlock-V1-ndk"],
     test_suites: [
         "general-tests",
         "vts",
diff --git a/power/1.0/vts/OWNERS b/power/1.0/vts/OWNERS
new file mode 100644
index 0000000..6de2cd5
--- /dev/null
+++ b/power/1.0/vts/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 158088
+connoro@google.com
diff --git a/power/1.1/vts/OWNERS b/power/1.1/vts/OWNERS
new file mode 100644
index 0000000..3a64da7
--- /dev/null
+++ b/power/1.1/vts/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 158088
+wvw@google.com
diff --git a/power/1.1/vts/functional/OWNERS b/power/1.1/vts/functional/OWNERS
new file mode 100644
index 0000000..6de2cd5
--- /dev/null
+++ b/power/1.1/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 158088
+connoro@google.com
diff --git a/power/1.2/vts/OWNERS b/power/1.2/vts/OWNERS
new file mode 100644
index 0000000..4d8c7e9
--- /dev/null
+++ b/power/1.2/vts/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 158088
+include ../../1.1/vts/OWNERS
diff --git a/power/1.3/vts/OWNERS b/power/1.3/vts/OWNERS
new file mode 100644
index 0000000..4d8c7e9
--- /dev/null
+++ b/power/1.3/vts/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 158088
+include ../../1.1/vts/OWNERS
diff --git a/power/aidl/default/Android.bp b/power/aidl/default/Android.bp
index c0ba9a0..9acb9e0 100644
--- a/power/aidl/default/Android.bp
+++ b/power/aidl/default/Android.bp
@@ -24,16 +24,26 @@
 cc_binary {
     name: "android.hardware.power-service.example",
     relative_install_path: "hw",
-    init_rc: ["power-default.rc"],
-    vintf_fragments: ["power-default.xml"],
+    init_rc: [":android.hardware.power.rc"],
+    vintf_fragments: [":android.hardware.power.xml"],
     vendor: true,
     shared_libs: [
         "libbase",
         "libbinder_ndk",
-        "android.hardware.power-V2-ndk_platform",
+        "android.hardware.power-V2-ndk",
     ],
     srcs: [
         "main.cpp",
         "Power.cpp",
     ],
 }
+
+filegroup {
+    name: "android.hardware.power.xml",
+    srcs: ["power-default.xml"],
+}
+
+filegroup {
+    name: "android.hardware.power.rc",
+    srcs: ["power-default.rc"],
+}
diff --git a/power/aidl/default/apex/Android.bp b/power/aidl/default/apex/Android.bp
new file mode 100644
index 0000000..eb04087
--- /dev/null
+++ b/power/aidl/default/apex/Android.bp
@@ -0,0 +1,72 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+apex_key {
+    name: "com.android.hardware.power.key",
+    public_key: "com.android.hardware.power.avbpubkey",
+    private_key: "com.android.hardware.power.pem",
+}
+
+android_app_certificate {
+    name: "com.android.hardware.power.certificate",
+    certificate: "com.android.hardware.power",
+}
+
+genrule {
+    name: "com.android.hardware.power.rc-srcs",
+    srcs: [
+        ":android.hardware.power.rc",
+        ":android.hardware.power.stats.rc",
+    ],
+    out: ["com.android.hardware.power.rc"],
+    cmd: "sed -E 's/\\/vendor/\\/apex\\/com.android.hardware.power/' $(in) > $(out)",
+}
+
+prebuilt_etc {
+    name: "com.android.hardware.power.rc",
+    src: ":com.android.hardware.power.rc-srcs",
+    installable: false,
+}
+
+apex {
+    name: "com.android.hardware.power",
+    manifest: "apex_manifest.json",
+    key: "com.android.hardware.power.key",
+    certificate: ":com.android.hardware.power.certificate",
+    file_contexts: "file_contexts",
+    use_vndk_as_stable: true,
+    updatable: false,
+    // Install the apex in /vendor/apex
+    soc_specific: true,
+    // Bundle the Power and PowerStats HALs into this one APEX.
+    binaries: [
+        "android.hardware.power-service.example",
+        "android.hardware.power.stats-service.example",
+    ],
+    prebuilts: [
+        "com.android.hardware.power.rc",
+    ],
+    vintf_fragments: [
+        ":android.hardware.power.xml",
+        ":android.hardware.power.stats.xml",
+    ],
+    overrides: [
+        // Shared lib installed by default but unused by the AIDL implementation.
+        "power.default",
+    ],
+}
diff --git a/power/aidl/default/apex/apex_manifest.json b/power/aidl/default/apex/apex_manifest.json
new file mode 100644
index 0000000..faa937d
--- /dev/null
+++ b/power/aidl/default/apex/apex_manifest.json
@@ -0,0 +1,4 @@
+{
+  "name": "com.android.hardware.power",
+  "version": 1
+}
diff --git a/power/aidl/default/apex/com.android.hardware.power.avbpubkey b/power/aidl/default/apex/com.android.hardware.power.avbpubkey
new file mode 100644
index 0000000..3b6411d
--- /dev/null
+++ b/power/aidl/default/apex/com.android.hardware.power.avbpubkey
Binary files differ
diff --git a/power/aidl/default/apex/com.android.hardware.power.pem b/power/aidl/default/apex/com.android.hardware.power.pem
new file mode 100644
index 0000000..d18ae98
--- /dev/null
+++ b/power/aidl/default/apex/com.android.hardware.power.pem
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIJKQIBAAKCAgEAsUdFjtLq05tWKdQd4aj8V7tmV4KXw41pKGT5Q1CPzrdHF3yJ
+B/8VWdMpjZ+eQO1q8SijPgfvWExeWQVMfxKmwTmj26xWXhIOgo5G02Zva7zOptig
+KGnl/RdFlOiIGC36XeWDhzdIOhlGv+er9Sykf6Ot84OvktTBUTZNJrXQsyYTBRUX
+6B+wloPdBVxVf1HgzjeHUyCy5dTz0xZSWWELoW24tHIvV5FtJVKSY8ZDfuXWLLfT
+he7E93TepjT027U/J/iW4ITJzw4Qq87ick1D/jZDUbTrkqUMFEgPdgCouZ9zt5xG
+pcHAZ/Fcz9DZfEdX9Xy0R5/XbfrJdvDPguJlwK1pZnr/Pe13xxmE+TEohMmaQDqX
+jQNX3UlcfOYUAjnFMGucHDM10KjTMbP8ytCys88aNLiv7FOgVGrQ/djZN8rkMyVP
+ccoksUBMQmjYaQQZ2yZuJMiLD3P6aYkgU5tMEMoMTrBzfcx05GfElal+ZqOFKAzj
+eUxoZTR27wJb684FRbeE45D+y4jpFfrTEXry+aI7GrfDsVDnUqmyObCUttRtaT04
+6kuUmC44wFEg1EBfcWZc1szI192GBjMuZjFcYvJ4vMdCuennqvLNPBDY1PtqzCOf
+D8vpOE3T9rjS23xxFmmSmorwKKQOGChKqO/SaY0axkXgt+FbSsvTBQtZTSsCAwEA
+AQKCAgEArEu3t+MYJcdwS8EDtcF2V5IkGmMrOvziOkdA14Kh8efBKXt49xOc3atU
+VHfQ6AuXh4DWf0BZB7lZbS2wNkSbW2q47ZSmcFEeVxcOkQGawtxDAHfD2ONrirqm
+ft4s/0sYbU/WsIEzKnxMfdEdGHFmA0PCmczfxFYQ+OxMuZW1m5ginirtDEZYa0EH
+e+FMmyypz+K6HDnIhYWd4Aduy718/0zTWlUr2/DUYpTJAD2+dcPNj7Kt2xq/xj2I
+84K+hBa4phF+GgIU3a8u1ryA61RbA+QbM3siBWlxvvh2RlrHoXjuj4JMS2dup9c2
+PCggaCAyxb2IvaAFUbePPJE5LVz6RFT4HnLEydd5Yt+CEAm+iZKfCzyUgFRtb5y0
+HHTME1eVAt/rf/yIXUYA7q8nQ/PtSzIol5KLX4FUjX1MVKNmIWMa+836kxbuYDFB
+K1M1IKc1k0t9Q9F3TRCMhP/6qH/vJfubCGQhSRUMq7JyjivK9GjYST8R07Dpgu9Z
+4i9TRI8d+UVERsg8niCXONVkmNa3U49u2duUvqV3KmKgQ/Hgyy3keDjz6x56ie5w
+e0EusHAsot60W1BvHrdwlmGZjW3JmZEyazUPh9nBUAaQve1rIOpn80kGXx4EAE2o
+HcrcInJx/zVBk1Wk3UQDwmhUNpa64q9+nd9VMaR9SQNK3ah4NDECggEBAOeput2F
+CgRrvzka69i7FbgY4VmpNMIICPIB6gxvwpir/g4/GgYknuBB6ep1ksf/IZfsMp5A
+JTH1KdXqqQm8nV9v+ETYQAO+VnmWKSBKHsNJqONxsKkQ+xIJcusmKBTYLfL88XQg
+YWH3VMXgqPP8DnJYCeVRIKj1WqfEFFHiaLJJB8FgKhtZBwBnibkVG1K0XCkTdUfY
+mME2GRKW/C7DMvuFOpcFVj7Obwn68R2k3zsOhWA5NQGZF5mqhg5KYLVDg3IbMJQQ
+D+DymQxnc2s2ar0q24isy1Y/FOXrA057j1vAN951+pk6F/PCJM/mtAiRjhP0Aru1
+P6bbR11p+wnpU7MCggEBAMPm8Jmwu3F0xsyFC+1sWPAzPiwaMa7/30wANNKKqHVO
+7lUv1WYFbFMyAOzYPp3Y5HxdxNa43reULGk0R20kSu6W6FkApSvAws0rLKRlS5UI
+oZqhLGHUH2M7q07m2RgQY2TJkU2Zq6AH1kjcbSr127ISXKanKpqonwSHy38BTcGt
+Dl2fVioPzK/vwmiNo2njhh95TV4kqlbUfl7xtDt56tbg8oFBwOsK7UGajXYOxTGB
+o1DtO5E+oiOmlclXuo3m4qpSSMv+wM91aRFhHZVIx0vmO8y5lrfU2kM/5DDhJBxV
+FM4TaA+c5tFOTuCLejHc7nM99wVx7O4QZ0wBwETUxKkCggEAH0tBT+1J1iEL+tXV
+KDjVjUHnJyqBUvis5Kw3hqiOO/t33UrO5CeMQrUEuURaqKOhURl6GQCHRcFdfmUt
+ooAVLjA89GfV9et/WPtc4NzCXRUVOGxCNgRyNhSKrpM/9NjjFCDxKQO6w/YaQITB
+rfvNo8qaw5x68ff64BDPweP4yqSs5IVuCrWzCW3zH8pnH3v3uyDCxgrPT8JUDrvQ
+oyyBNZLgwEfbR66xN0Lr0VpVQXALulzf+TBKDNsJMuL/P104Y3Ci1k15J6T94bwT
+zlbSgm1IrKTS7vqkgw6FKtPsILPNmEKNsKc1VxtRx7fdeA7Zh3595Adu6sZSVJ8d
+Z1BamwKCAQAnbu0vgqu4gtEhigaEnDKq5yW0qvElUMwZ+FCpsM+IDYNcEmzaRG0x
+sfcNtdmk3GvhvN5KepwaR/FInAVkqtGKhUXv5Hla/Uo5El/CF8HHFh2xio/sgU5w
+IyqwjzdT6LiZKRnejPhHFkzEDdrLswGuLpQH185zo02fE9aakiCcw8EIh3JItTV2
+lMSFVz11qx7sZvZz5N2E7PEjG3Q0JK5o4o7uBdZXebOYaQvgn8iB1p6RQ6+h5QGu
+O3IbPVWICtnFfxq4NWeKWw/zN6FE04mKdaXD5/e2uVnV/55nWGp0aYvuj2l6+xJb
+P3ARMwI910MIX4jBx9TxdsvUOOYC9PFBAoIBAQDWswLnaNth4pgutngVWbMenSpv
+eK1RA1ldw2NoTZrGlqPB+LvjEMSH/7ioby8YtOyJRIWs3si8HpVF12qneu8qi7b7
+QlUtqyJOTnGalvhrlq5zPhdW+kk2DXvtTylUnz3vSxxi2I7cLhQRryLC/1kAwy67
+wEr0+u59bOvaqe8L1zgtYJpLQZeskUMzdSMIRVDdFShEFrMJU7adUvGpA7OZ6Ogf
+ux2jWr2vv/eKq6fU6kDPi/66MQjPbZPf2Uq6+XedkNkAeELpN4o3hw0/l/rfiK/r
+YUMJBwtjQw/hehtvC4GlgsH1tMZWzCZULo0tcW4qbzyi9PBrWFPteb33OjBc
+-----END RSA PRIVATE KEY-----
diff --git a/power/aidl/default/apex/com.android.hardware.power.pk8 b/power/aidl/default/apex/com.android.hardware.power.pk8
new file mode 100644
index 0000000..e45435d
--- /dev/null
+++ b/power/aidl/default/apex/com.android.hardware.power.pk8
Binary files differ
diff --git a/power/aidl/default/apex/com.android.hardware.power.x509.pem b/power/aidl/default/apex/com.android.hardware.power.x509.pem
new file mode 100644
index 0000000..9f0c5f0
--- /dev/null
+++ b/power/aidl/default/apex/com.android.hardware.power.x509.pem
@@ -0,0 +1,34 @@
+-----BEGIN CERTIFICATE-----
+MIIF2TCCA8ECFDFsXbm5CdS/UtQZgTiF8Umr8LrLMA0GCSqGSIb3DQEBCwUAMIGn
+MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
+bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
+MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTEjMCEGA1UEAwwaY29t
+LmFuZHJvaWQuaGFyZHdhcmUucG93ZXIwIBcNMjExMDIwMTcwNTA0WhgPNDc1OTA5
+MTYxNzA1MDRaMIGnMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEW
+MBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UE
+CwwHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTEj
+MCEGA1UEAwwaY29tLmFuZHJvaWQuaGFyZHdhcmUucG93ZXIwggIiMA0GCSqGSIb3
+DQEBAQUAA4ICDwAwggIKAoICAQC/37fhOkOfgM2e+M7bMJ1baLFif8dKGwRa6mkJ
+9HWmuOgRcTKllzuEHtrJ0jzur3cDy6/0oZSfA/E1ck3DdRHMQadW26JSNSg6fCU9
+h1kDzkakZgyr3DsJnKGoSHCJ2V2kVbCnd6GuOaOU1ZZISw1I+BWJDc3t1mZPs80D
+ar7/hoIZnsWRoE/eWgJDcWWscRsquSi+q6hyqlCbRvwRznPaDGwmb4geHNugCXkz
+EtCswfc5jiT8DjMDkgVsGO/WcYj2GWT0K0H+Zf1CmEO9fAoXTLfVBjdumtGILgii
+d/TJe2tOBSWyZz6sVzfac2PvUH5Lm8TNUXuLV5IEdcpySge0vqYQwAyd2EgsTH1e
+mRNSk9NerpmfCFEySRRP3BWMGRhbST1d8M3v9Bq0QFhrxoAF12r6GXBUpp9XcOL5
+pBTcAkA9XI++mfz4pDzyGRGOy4WX+8XtsaVZ/14JklupSLr0Tt7oaNocUhoXB03g
+4B0jUTX0hNnVzCxzJypw6YJ60Zc8z+z8pEF34FWarHec1QbkFuyWxbaTPQ4d2NLH
+8zDxQpMILErWdAgKsRL0d8RFG5fBcleEoBM2kKHMAgnP+1qyDqBgt8zloWbmmblw
+JXMuoePFOgeVcgPrZ3EGJSx+s4+dQGQc6r/GwKLKSWpUvHxTIGug76IX9xmptB+I
+F3xb2QIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQANISf3Vi2eueOlzzfnEGGa+CXz
+nvlgUXKv8Gv0/Pbg5uC1BaHTAUgRu5rvrfP9p3Mdj86I/HbE/F4Vkuzqb8/JTWGA
+mG636zAsJRJr0fnkbPma9wVEPSK8MF1QqM6PmKXboixX82TqV1R1sRYG+9hh9W3u
+isDzYDb2ODE0X9M8/3hLS28zdCdtl4zCRK6KB86aGxvkVEj4qDA5l+AbVYevS/SU
+hz1+K/aM0Fi6MZovo5kd/Mof5l05e1TEgCoL1FtFX79r+PYGHJ8/LjtEMkFgwqvG
+CLx2sOV09EHZU27EbVvSs1JYMMXgeAvKaHsVZ51QlSzW4esg/E6z4pw654p8qyK/
+WLXIZ7BMILl1sHYmGqXitnu19puvNks2/+hyqVr0seM5GyQDuwBE8nx6xZzTRxdj
+4TZyN9LuMc9/cKJFvOPqD152bkA2frCLEzYCQreDWwxsWcUHzYrQT+v2SqzP6Ue2
+Xn06HDLx9wBL7Dz6no05SlNS0u1KdvKas6FKZHO+QaKKsBlDmXbMrBTcuUI6OXv2
+6NpVbeyDd0+A23hDiNSgI6zTY6jMidesNExB7rW/bCE4ltPyxFAB+sffyXounODc
+groB5CaS2bv+H1IXJzMMe4LkgQPl1C7G+I3KvJmnrYwmIhLIDuxP82arClIDzccS
+ExRR7ugEg91XCc87Zg==
+-----END CERTIFICATE-----
diff --git a/power/aidl/default/apex/file_contexts b/power/aidl/default/apex/file_contexts
new file mode 100644
index 0000000..3433851
--- /dev/null
+++ b/power/aidl/default/apex/file_contexts
@@ -0,0 +1,3 @@
+(/.*)?                                                      u:object_r:vendor_file:s0
+/bin/hw/android\.hardware\.power-service\.example           u:object_r:hal_power_default_exec:s0
+/bin/hw/android\.hardware\.power\.stats-service\.example    u:object_r:hal_power_stats_default_exec:s0
diff --git a/power/aidl/default/main.cpp b/power/aidl/default/main.cpp
index 964bd96..306b91b 100644
--- a/power/aidl/default/main.cpp
+++ b/power/aidl/default/main.cpp
@@ -28,7 +28,7 @@
 
     const std::string instance = std::string() + Power::descriptor + "/default";
     binder_status_t status = AServiceManager_addService(vib->asBinder().get(), instance.c_str());
-    CHECK(status == STATUS_OK);
+    CHECK_EQ(status, STATUS_OK);
 
     ABinderProcess_joinThreadPool();
     return EXIT_FAILURE;  // should not reach
diff --git a/power/aidl/vts/Android.bp b/power/aidl/vts/Android.bp
index 3036b82..eccd872 100644
--- a/power/aidl/vts/Android.bp
+++ b/power/aidl/vts/Android.bp
@@ -32,7 +32,7 @@
         "libbinder_ndk",
     ],
     static_libs: [
-        "android.hardware.power-V2-ndk_platform",
+        "android.hardware.power-V2-ndk",
     ],
     test_suites: [
         "vts",
diff --git a/power/stats/1.0/vts/functional/OWNERS b/power/stats/1.0/vts/functional/OWNERS
new file mode 100644
index 0000000..8dd30e0
--- /dev/null
+++ b/power/stats/1.0/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 709877
+bsschwar@google.com
diff --git a/power/stats/aidl/default/Android.bp b/power/stats/aidl/default/Android.bp
index 417dc97..66be5f9 100644
--- a/power/stats/aidl/default/Android.bp
+++ b/power/stats/aidl/default/Android.bp
@@ -24,16 +24,26 @@
 cc_binary {
     name: "android.hardware.power.stats-service.example",
     relative_install_path: "hw",
-    init_rc: ["power.stats-default.rc"],
-    vintf_fragments: ["power.stats-default.xml"],
+    init_rc: [":android.hardware.power.stats.rc"],
+    vintf_fragments: [":android.hardware.power.stats.xml"],
     vendor: true,
     shared_libs: [
         "libbase",
         "libbinder_ndk",
-        "android.hardware.power.stats-V1-ndk_platform",
+        "android.hardware.power.stats-V1-ndk",
     ],
     srcs: [
         "main.cpp",
         "PowerStats.cpp",
     ],
 }
+
+filegroup {
+    name: "android.hardware.power.stats.xml",
+    srcs: ["power.stats-default.xml"],
+}
+
+filegroup {
+    name: "android.hardware.power.stats.rc",
+    srcs: ["power.stats-default.rc"],
+}
diff --git a/power/stats/aidl/default/main.cpp b/power/stats/aidl/default/main.cpp
index 2fe3d2e..9e78247 100644
--- a/power/stats/aidl/default/main.cpp
+++ b/power/stats/aidl/default/main.cpp
@@ -73,7 +73,7 @@
 
     const std::string instance = std::string() + PowerStats::descriptor + "/default";
     binder_status_t status = AServiceManager_addService(p->asBinder().get(), instance.c_str());
-    CHECK(status == STATUS_OK);
+    CHECK_EQ(status, STATUS_OK);
 
     ABinderProcess_joinThreadPool();
     return EXIT_FAILURE;  // should not reach
diff --git a/power/stats/aidl/vts/Android.bp b/power/stats/aidl/vts/Android.bp
index b556548..b9a395b 100644
--- a/power/stats/aidl/vts/Android.bp
+++ b/power/stats/aidl/vts/Android.bp
@@ -32,7 +32,7 @@
         "libbinder_ndk",
     ],
     static_libs: [
-        "android.hardware.power.stats-V1-ndk_platform",
+        "android.hardware.power.stats-V1-ndk",
     ],
     test_suites: [
         "general-tests",
diff --git a/radio/1.0/Android.bp b/radio/1.0/Android.bp
index cd64bca..8d0d782 100644
--- a/radio/1.0/Android.bp
+++ b/radio/1.0/Android.bp
@@ -23,5 +23,9 @@
     interfaces: [
         "android.hidl.base@1.0",
     ],
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.bluetooth",
+    ],
     gen_java: true,
 }
diff --git a/radio/1.0/vts/OWNERS b/radio/1.0/vts/OWNERS
index 9310f8e..117692a 100644
--- a/radio/1.0/vts/OWNERS
+++ b/radio/1.0/vts/OWNERS
@@ -1,7 +1,5 @@
-# Telephony team
-amitmahajan@google.com
+# Bug component: 20868
+jminjie@google.com
+sarahchin@google.com
 shuoq@google.com
 jackyu@google.com
-
-# VTS team
-dshi@google.com
diff --git a/radio/1.0/vts/functional/OWNERS b/radio/1.0/vts/functional/OWNERS
new file mode 100644
index 0000000..1b6d937
--- /dev/null
+++ b/radio/1.0/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 20868
+shuoq@google.com
diff --git a/radio/1.0/vts/functional/sap_hidl_hal_test.cpp b/radio/1.0/vts/functional/sap_hidl_hal_test.cpp
index fe10587..5224624 100644
--- a/radio/1.0/vts/functional/sap_hidl_hal_test.cpp
+++ b/radio/1.0/vts/functional/sap_hidl_hal_test.cpp
@@ -16,8 +16,37 @@
 
 #include <sap_hidl_hal_utils.h>
 
+bool isServiceValidForDeviceConfiguration(hidl_string& serviceName) {
+    if (isSsSsEnabled()) {
+        // Device is configured as SSSS.
+        if (serviceName != SAP_SERVICE_SLOT1_NAME) {
+            LOG(DEBUG) << "Not valid for SSSS device.";
+            return false;
+        }
+    } else if (isDsDsEnabled()) {
+        // Device is configured as DSDS.
+        if (serviceName != SAP_SERVICE_SLOT1_NAME && serviceName != SAP_SERVICE_SLOT2_NAME) {
+            LOG(DEBUG) << "Not valid for DSDS device.";
+            return false;
+        }
+    } else if (isTsTsEnabled()) {
+        // Device is configured as TSTS.
+        if (serviceName != SAP_SERVICE_SLOT1_NAME && serviceName != SAP_SERVICE_SLOT2_NAME &&
+            serviceName != SAP_SERVICE_SLOT3_NAME) {
+            LOG(DEBUG) << "Not valid for TSTS device.";
+            return false;
+        }
+    }
+    return true;
+}
+
 void SapHidlTest::SetUp() {
-    sap = ISap::getService(GetParam());
+    hidl_string serviceName = GetParam();
+    if (!isServiceValidForDeviceConfiguration(serviceName)) {
+        LOG(DEBUG) << "Skipped the test due to device configuration.";
+        GTEST_SKIP();
+    }
+    sap = ISap::getService(serviceName);
     ASSERT_NE(sap, nullptr);
 
     sapCb = new SapCallback(*this);
diff --git a/radio/1.0/vts/functional/sap_hidl_hal_utils.h b/radio/1.0/vts/functional/sap_hidl_hal_utils.h
index 2fc9ae3..8e86591 100644
--- a/radio/1.0/vts/functional/sap_hidl_hal_utils.h
+++ b/radio/1.0/vts/functional/sap_hidl_hal_utils.h
@@ -36,7 +36,15 @@
 using ::android::sp;
 
 #define TIMEOUT_PERIOD 40
-#define SAP_SERVICE_NAME "slot1"
+
+// HAL instance name for SIM slot 1 or single SIM device
+#define SAP_SERVICE_SLOT1_NAME "slot1"
+
+// HAL instance name for SIM slot 2 on dual SIM device
+#define SAP_SERVICE_SLOT2_NAME "slot2"
+
+// HAL instance name for SIM slot 3 on triple SIM device
+#define SAP_SERVICE_SLOT3_NAME "slot3"
 
 class SapHidlTest;
 
diff --git a/radio/1.1/vts/OWNERS b/radio/1.1/vts/OWNERS
index a07c917..4d199ca 100644
--- a/radio/1.1/vts/OWNERS
+++ b/radio/1.1/vts/OWNERS
@@ -1 +1,2 @@
+# Bug component: 20868
 include ../../1.0/vts/OWNERS
diff --git a/radio/1.2/vts/OWNERS b/radio/1.2/vts/OWNERS
index a07c917..4d199ca 100644
--- a/radio/1.2/vts/OWNERS
+++ b/radio/1.2/vts/OWNERS
@@ -1 +1,2 @@
+# Bug component: 20868
 include ../../1.0/vts/OWNERS
diff --git a/radio/1.3/vts/OWNERS b/radio/1.3/vts/OWNERS
index a07c917..4d199ca 100644
--- a/radio/1.3/vts/OWNERS
+++ b/radio/1.3/vts/OWNERS
@@ -1 +1,2 @@
+# Bug component: 20868
 include ../../1.0/vts/OWNERS
diff --git a/radio/1.4/vts/OWNERS b/radio/1.4/vts/OWNERS
index a07c917..4d199ca 100644
--- a/radio/1.4/vts/OWNERS
+++ b/radio/1.4/vts/OWNERS
@@ -1 +1,2 @@
+# Bug component: 20868
 include ../../1.0/vts/OWNERS
diff --git a/radio/1.5/vts/OWNERS b/radio/1.5/vts/OWNERS
index a07c917..4d199ca 100644
--- a/radio/1.5/vts/OWNERS
+++ b/radio/1.5/vts/OWNERS
@@ -1 +1,2 @@
+# Bug component: 20868
 include ../../1.0/vts/OWNERS
diff --git a/radio/1.6/vts/functional/radio_hidl_hal_api.cpp b/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
index 4549f51..9f530b3 100644
--- a/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
@@ -595,14 +595,11 @@
     EXPECT_EQ(std::cv_status::no_timeout, wait());
     EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
     EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
-    ASSERT_TRUE(
-            CheckAnyOfErrors(radioRsp_v1_6->rspInfo.error,
-                             {::android::hardware::radio::V1_6::RadioError::NONE,
-                              ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
-                              ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE}));
-
-    // Give some time for modem to fully power up the SIM card
-    sleep(MODEM_SET_SIM_POWER_DELAY_IN_SECONDS);
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_6->rspInfo.error,
+                                 {::android::hardware::radio::V1_6::RadioError::NONE,
+                                  ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
+                                  ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+                                  ::android::hardware::radio::V1_6::RadioError::SIM_ERR}));
 
     // setSimCardPower_1_6 does not return  until the request is handled, and should not trigger
     // CardState::ABSENT when turning off power
@@ -615,17 +612,20 @@
         EXPECT_EQ(0, cardStatus.applications.size());
     }
 
+    // Give some time for modem to fully power down the SIM card
+    sleep(MODEM_SET_SIM_POWER_DELAY_IN_SECONDS);
+
     /* Test setSimCardPower power up */
     serial = GetRandomSerialNumber();
     radio_v1_6->setSimCardPower_1_6(serial, CardPowerState::POWER_UP);
     EXPECT_EQ(std::cv_status::no_timeout, wait());
     EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
     EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
-    ASSERT_TRUE(
-            CheckAnyOfErrors(radioRsp_v1_6->rspInfo.error,
-                             {::android::hardware::radio::V1_6::RadioError::NONE,
-                              ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
-                              ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE}));
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_6->rspInfo.error,
+                                 {::android::hardware::radio::V1_6::RadioError::NONE,
+                                  ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
+                                  ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+                                  ::android::hardware::radio::V1_6::RadioError::SIM_ERR}));
 
     // Give some time for modem to fully power up the SIM card
     sleep(MODEM_SET_SIM_POWER_DELAY_IN_SECONDS);
diff --git a/radio/aidl/Android.bp b/radio/aidl/Android.bp
new file mode 100644
index 0000000..e1808af
--- /dev/null
+++ b/radio/aidl/Android.bp
@@ -0,0 +1,186 @@
+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.radio",
+    vendor_available: true,
+    host_supported: true,
+    srcs: ["android/hardware/radio/*.aidl"],
+    stability: "vintf",
+    backend: {
+        cpp: {
+            enabled: false,
+        },
+        java: {
+            sdk_version: "module_current",
+        },
+        ndk: {
+            vndk: {
+                enabled: true,
+            },
+        },
+    },
+}
+
+aidl_interface {
+    name: "android.hardware.radio.config",
+    vendor_available: true,
+    host_supported: true,
+    srcs: ["android/hardware/radio/config/*.aidl"],
+    stability: "vintf",
+    imports: ["android.hardware.radio"],
+    backend: {
+        cpp: {
+            enabled: false,
+        },
+        java: {
+            sdk_version: "module_current",
+        },
+        ndk: {
+            vndk: {
+                enabled: true,
+            },
+        },
+    },
+}
+
+aidl_interface {
+    name: "android.hardware.radio.data",
+    vendor_available: true,
+    host_supported: true,
+    srcs: ["android/hardware/radio/data/*.aidl"],
+    stability: "vintf",
+    imports: ["android.hardware.radio"],
+    backend: {
+        cpp: {
+            enabled: false,
+        },
+        java: {
+            sdk_version: "module_current",
+        },
+        ndk: {
+            vndk: {
+                enabled: true,
+            },
+        },
+    },
+}
+
+aidl_interface {
+    name: "android.hardware.radio.messaging",
+    vendor_available: true,
+    host_supported: true,
+    srcs: ["android/hardware/radio/messaging/*.aidl"],
+    stability: "vintf",
+    imports: ["android.hardware.radio"],
+    backend: {
+        cpp: {
+            enabled: false,
+        },
+        java: {
+            sdk_version: "module_current",
+        },
+        ndk: {
+            vndk: {
+                enabled: true,
+            },
+        },
+    },
+}
+
+aidl_interface {
+    name: "android.hardware.radio.modem",
+    vendor_available: true,
+    host_supported: true,
+    srcs: ["android/hardware/radio/modem/*.aidl"],
+    stability: "vintf",
+    imports: ["android.hardware.radio"],
+    backend: {
+        cpp: {
+            enabled: false,
+        },
+        java: {
+            sdk_version: "module_current",
+        },
+        ndk: {
+            vndk: {
+                enabled: true,
+            },
+        },
+    },
+}
+
+aidl_interface {
+    name: "android.hardware.radio.network",
+    vendor_available: true,
+    host_supported: true,
+    srcs: ["android/hardware/radio/network/*.aidl"],
+    stability: "vintf",
+    imports: ["android.hardware.radio"],
+    backend: {
+        cpp: {
+            enabled: false,
+        },
+        java: {
+            sdk_version: "module_current",
+        },
+        ndk: {
+            vndk: {
+                enabled: true,
+            },
+        },
+    },
+}
+
+aidl_interface {
+    name: "android.hardware.radio.sim",
+    vendor_available: true,
+    host_supported: true,
+    srcs: ["android/hardware/radio/sim/*.aidl"],
+    stability: "vintf",
+    imports: [
+        "android.hardware.radio",
+        "android.hardware.radio.config",
+    ],
+    backend: {
+        cpp: {
+            enabled: false,
+        },
+        java: {
+            sdk_version: "module_current",
+        },
+        ndk: {
+            vndk: {
+                enabled: true,
+            },
+        },
+    },
+}
+
+aidl_interface {
+    name: "android.hardware.radio.voice",
+    vendor_available: true,
+    host_supported: true,
+    srcs: ["android/hardware/radio/voice/*.aidl"],
+    stability: "vintf",
+    imports: ["android.hardware.radio"],
+    backend: {
+        cpp: {
+            enabled: false,
+        },
+        java: {
+            sdk_version: "module_current",
+        },
+        ndk: {
+            vndk: {
+                enabled: true,
+            },
+        },
+    },
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfig.aidl b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfig.aidl
new file mode 100644
index 0000000..a48a89b
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfig.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *
+ * This interface is used by telephony and telecom to talk to cellular radio for the purpose of
+ * radio configuration, and it is not associated with any specific modem or slot.
+ * All the functions have minimum one parameter:
+ * serial: which corresponds to serial no. of request. Serial numbers must only be memorized for the
+ * duration of a method call. If clients provide colliding serials (including passing the same
+ * serial to different methods), multiple responses (one for each method call) must still be served.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.radio.config;
+@VintfStability
+interface IRadioConfig {
+  oneway void getHalDeviceCapabilities(in int serial);
+  oneway void getNumOfLiveModems(in int serial);
+  oneway void getPhoneCapability(in int serial);
+  oneway void getSimSlotsStatus(in int serial);
+  oneway void setNumOfLiveModems(in int serial, in byte numOfLiveModems);
+  oneway void setPreferredDataModem(in int serial, in byte modemId);
+  oneway void setResponseFunctions(in android.hardware.radio.config.IRadioConfigResponse radioConfigResponse, in android.hardware.radio.config.IRadioConfigIndication radioConfigIndication);
+  oneway void setSimSlotsMapping(in int serial, in android.hardware.radio.config.SlotPortMapping[] slotMap);
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfigIndication.aidl b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfigIndication.aidl
new file mode 100644
index 0000000..994e337
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfigIndication.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.config;
+@VintfStability
+interface IRadioConfigIndication {
+  oneway void simSlotsStatusChanged(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.config.SimSlotStatus[] slotStatus);
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfigResponse.aidl b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfigResponse.aidl
new file mode 100644
index 0000000..038b0ae
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/IRadioConfigResponse.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.config;
+@VintfStability
+interface IRadioConfigResponse {
+  oneway void getHalDeviceCapabilitiesResponse(in android.hardware.radio.RadioResponseInfo info, in boolean modemReducedFeatureSet1);
+  oneway void getNumOfLiveModemsResponse(in android.hardware.radio.RadioResponseInfo info, in byte numOfLiveModems);
+  oneway void getPhoneCapabilityResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.config.PhoneCapability phoneCapability);
+  oneway void getSimSlotsStatusResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.config.SimSlotStatus[] slotStatus);
+  oneway void setNumOfLiveModemsResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setPreferredDataModemResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setSimSlotsMappingResponse(in android.hardware.radio.RadioResponseInfo info);
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/PhoneCapability.aidl b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/PhoneCapability.aidl
new file mode 100644
index 0000000..db3a4c6
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/PhoneCapability.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.config;
+@JavaDerive(toString=true) @VintfStability
+parcelable PhoneCapability {
+  byte maxActiveData;
+  byte maxActiveInternetData;
+  boolean isInternetLingeringSupported;
+  byte[] logicalModemIds;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/SimPortInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/SimPortInfo.aidl
new file mode 100644
index 0000000..b5d31ad
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/SimPortInfo.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.config;
+@JavaDerive(toString=true) @VintfStability
+parcelable SimPortInfo {
+  String iccId;
+  int logicalSlotId;
+  boolean portActive;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/SimSlotStatus.aidl b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/SimSlotStatus.aidl
new file mode 100644
index 0000000..be4c080
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/SimSlotStatus.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.config;
+@JavaDerive(toString=true) @VintfStability
+parcelable SimSlotStatus {
+  int cardState;
+  String atr;
+  String eid;
+  android.hardware.radio.config.SimPortInfo[] portInfo;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/SlotPortMapping.aidl b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/SlotPortMapping.aidl
new file mode 100644
index 0000000..31271ee
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/SlotPortMapping.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.config;
+@JavaDerive(toString=true) @VintfStability
+parcelable SlotPortMapping {
+  int physicalSlotId;
+  int portId;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnAuthType.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnAuthType.aidl
new file mode 100644
index 0000000..86272c2
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnAuthType.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.data;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum ApnAuthType {
+  NO_PAP_NO_CHAP = 0,
+  PAP_NO_CHAP = 1,
+  NO_PAP_CHAP = 2,
+  PAP_CHAP = 3,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnTypes.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnTypes.aidl
new file mode 100644
index 0000000..1518a57
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnTypes.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.data;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum ApnTypes {
+  NONE = 0,
+  DEFAULT = 1,
+  MMS = 2,
+  SUPL = 4,
+  DUN = 8,
+  HIPRI = 16,
+  FOTA = 32,
+  IMS = 64,
+  CBS = 128,
+  IA = 256,
+  EMERGENCY = 512,
+  MCX = 1024,
+  XCAP = 2048,
+  VSIM = 4096,
+  BIP = 8192,
+  ENTERPRISE = 16384,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataCallFailCause.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataCallFailCause.aidl
new file mode 100644
index 0000000..d7d6983
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataCallFailCause.aidl
@@ -0,0 +1,377 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.data;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum DataCallFailCause {
+  NONE = 0,
+  OPERATOR_BARRED = 8,
+  NAS_SIGNALLING = 14,
+  INSUFFICIENT_RESOURCES = 26,
+  MISSING_UNKNOWN_APN = 27,
+  UNKNOWN_PDP_ADDRESS_TYPE = 28,
+  USER_AUTHENTICATION = 29,
+  ACTIVATION_REJECT_GGSN = 30,
+  ACTIVATION_REJECT_UNSPECIFIED = 31,
+  SERVICE_OPTION_NOT_SUPPORTED = 32,
+  SERVICE_OPTION_NOT_SUBSCRIBED = 33,
+  SERVICE_OPTION_OUT_OF_ORDER = 34,
+  NSAPI_IN_USE = 35,
+  REGULAR_DEACTIVATION = 36,
+  QOS_NOT_ACCEPTED = 37,
+  NETWORK_FAILURE = 38,
+  UMTS_REACTIVATION_REQ = 39,
+  FEATURE_NOT_SUPP = 40,
+  TFT_SEMANTIC_ERROR = 41,
+  TFT_SYTAX_ERROR = 42,
+  UNKNOWN_PDP_CONTEXT = 43,
+  FILTER_SEMANTIC_ERROR = 44,
+  FILTER_SYTAX_ERROR = 45,
+  PDP_WITHOUT_ACTIVE_TFT = 46,
+  ONLY_IPV4_ALLOWED = 50,
+  ONLY_IPV6_ALLOWED = 51,
+  ONLY_SINGLE_BEARER_ALLOWED = 52,
+  ESM_INFO_NOT_RECEIVED = 53,
+  PDN_CONN_DOES_NOT_EXIST = 54,
+  MULTI_CONN_TO_SAME_PDN_NOT_ALLOWED = 55,
+  MAX_ACTIVE_PDP_CONTEXT_REACHED = 65,
+  UNSUPPORTED_APN_IN_CURRENT_PLMN = 66,
+  INVALID_TRANSACTION_ID = 81,
+  MESSAGE_INCORRECT_SEMANTIC = 95,
+  INVALID_MANDATORY_INFO = 96,
+  MESSAGE_TYPE_UNSUPPORTED = 97,
+  MSG_TYPE_NONCOMPATIBLE_STATE = 98,
+  UNKNOWN_INFO_ELEMENT = 99,
+  CONDITIONAL_IE_ERROR = 100,
+  MSG_AND_PROTOCOL_STATE_UNCOMPATIBLE = 101,
+  PROTOCOL_ERRORS = 111,
+  APN_TYPE_CONFLICT = 112,
+  INVALID_PCSCF_ADDR = 113,
+  INTERNAL_CALL_PREEMPT_BY_HIGH_PRIO_APN = 114,
+  EMM_ACCESS_BARRED = 115,
+  EMERGENCY_IFACE_ONLY = 116,
+  IFACE_MISMATCH = 117,
+  COMPANION_IFACE_IN_USE = 118,
+  IP_ADDRESS_MISMATCH = 119,
+  IFACE_AND_POL_FAMILY_MISMATCH = 120,
+  EMM_ACCESS_BARRED_INFINITE_RETRY = 121,
+  AUTH_FAILURE_ON_EMERGENCY_CALL = 122,
+  OEM_DCFAILCAUSE_1 = 4097,
+  OEM_DCFAILCAUSE_2 = 4098,
+  OEM_DCFAILCAUSE_3 = 4099,
+  OEM_DCFAILCAUSE_4 = 4100,
+  OEM_DCFAILCAUSE_5 = 4101,
+  OEM_DCFAILCAUSE_6 = 4102,
+  OEM_DCFAILCAUSE_7 = 4103,
+  OEM_DCFAILCAUSE_8 = 4104,
+  OEM_DCFAILCAUSE_9 = 4105,
+  OEM_DCFAILCAUSE_10 = 4106,
+  OEM_DCFAILCAUSE_11 = 4107,
+  OEM_DCFAILCAUSE_12 = 4108,
+  OEM_DCFAILCAUSE_13 = 4109,
+  OEM_DCFAILCAUSE_14 = 4110,
+  OEM_DCFAILCAUSE_15 = 4111,
+  VOICE_REGISTRATION_FAIL = -1,
+  DATA_REGISTRATION_FAIL = -2,
+  SIGNAL_LOST = -3,
+  PREF_RADIO_TECH_CHANGED = -4,
+  RADIO_POWER_OFF = -5,
+  TETHERED_CALL_ACTIVE = -6,
+  ERROR_UNSPECIFIED = 65535,
+  LLC_SNDCP = 25,
+  ACTIVATION_REJECTED_BCM_VIOLATION = 48,
+  COLLISION_WITH_NETWORK_INITIATED_REQUEST = 56,
+  ONLY_IPV4V6_ALLOWED = 57,
+  ONLY_NON_IP_ALLOWED = 58,
+  UNSUPPORTED_QCI_VALUE = 59,
+  BEARER_HANDLING_NOT_SUPPORTED = 60,
+  INVALID_DNS_ADDR = 123,
+  INVALID_PCSCF_OR_DNS_ADDRESS = 124,
+  CALL_PREEMPT_BY_EMERGENCY_APN = 127,
+  UE_INITIATED_DETACH_OR_DISCONNECT = 128,
+  MIP_FA_REASON_UNSPECIFIED = 2000,
+  MIP_FA_ADMIN_PROHIBITED = 2001,
+  MIP_FA_INSUFFICIENT_RESOURCES = 2002,
+  MIP_FA_MOBILE_NODE_AUTHENTICATION_FAILURE = 2003,
+  MIP_FA_HOME_AGENT_AUTHENTICATION_FAILURE = 2004,
+  MIP_FA_REQUESTED_LIFETIME_TOO_LONG = 2005,
+  MIP_FA_MALFORMED_REQUEST = 2006,
+  MIP_FA_MALFORMED_REPLY = 2007,
+  MIP_FA_ENCAPSULATION_UNAVAILABLE = 2008,
+  MIP_FA_VJ_HEADER_COMPRESSION_UNAVAILABLE = 2009,
+  MIP_FA_REVERSE_TUNNEL_UNAVAILABLE = 2010,
+  MIP_FA_REVERSE_TUNNEL_IS_MANDATORY = 2011,
+  MIP_FA_DELIVERY_STYLE_NOT_SUPPORTED = 2012,
+  MIP_FA_MISSING_NAI = 2013,
+  MIP_FA_MISSING_HOME_AGENT = 2014,
+  MIP_FA_MISSING_HOME_ADDRESS = 2015,
+  MIP_FA_UNKNOWN_CHALLENGE = 2016,
+  MIP_FA_MISSING_CHALLENGE = 2017,
+  MIP_FA_STALE_CHALLENGE = 2018,
+  MIP_HA_REASON_UNSPECIFIED = 2019,
+  MIP_HA_ADMIN_PROHIBITED = 2020,
+  MIP_HA_INSUFFICIENT_RESOURCES = 2021,
+  MIP_HA_MOBILE_NODE_AUTHENTICATION_FAILURE = 2022,
+  MIP_HA_FOREIGN_AGENT_AUTHENTICATION_FAILURE = 2023,
+  MIP_HA_REGISTRATION_ID_MISMATCH = 2024,
+  MIP_HA_MALFORMED_REQUEST = 2025,
+  MIP_HA_UNKNOWN_HOME_AGENT_ADDRESS = 2026,
+  MIP_HA_REVERSE_TUNNEL_UNAVAILABLE = 2027,
+  MIP_HA_REVERSE_TUNNEL_IS_MANDATORY = 2028,
+  MIP_HA_ENCAPSULATION_UNAVAILABLE = 2029,
+  CLOSE_IN_PROGRESS = 2030,
+  NETWORK_INITIATED_TERMINATION = 2031,
+  MODEM_APP_PREEMPTED = 2032,
+  PDN_IPV4_CALL_DISALLOWED = 2033,
+  PDN_IPV4_CALL_THROTTLED = 2034,
+  PDN_IPV6_CALL_DISALLOWED = 2035,
+  PDN_IPV6_CALL_THROTTLED = 2036,
+  MODEM_RESTART = 2037,
+  PDP_PPP_NOT_SUPPORTED = 2038,
+  UNPREFERRED_RAT = 2039,
+  PHYSICAL_LINK_CLOSE_IN_PROGRESS = 2040,
+  APN_PENDING_HANDOVER = 2041,
+  PROFILE_BEARER_INCOMPATIBLE = 2042,
+  SIM_CARD_CHANGED = 2043,
+  LOW_POWER_MODE_OR_POWERING_DOWN = 2044,
+  APN_DISABLED = 2045,
+  MAX_PPP_INACTIVITY_TIMER_EXPIRED = 2046,
+  IPV6_ADDRESS_TRANSFER_FAILED = 2047,
+  TRAT_SWAP_FAILED = 2048,
+  EHRPD_TO_HRPD_FALLBACK = 2049,
+  MIP_CONFIG_FAILURE = 2050,
+  PDN_INACTIVITY_TIMER_EXPIRED = 2051,
+  MAX_IPV4_CONNECTIONS = 2052,
+  MAX_IPV6_CONNECTIONS = 2053,
+  APN_MISMATCH = 2054,
+  IP_VERSION_MISMATCH = 2055,
+  DUN_CALL_DISALLOWED = 2056,
+  INTERNAL_EPC_NONEPC_TRANSITION = 2057,
+  INTERFACE_IN_USE = 2058,
+  APN_DISALLOWED_ON_ROAMING = 2059,
+  APN_PARAMETERS_CHANGED = 2060,
+  NULL_APN_DISALLOWED = 2061,
+  THERMAL_MITIGATION = 2062,
+  DATA_SETTINGS_DISABLED = 2063,
+  DATA_ROAMING_SETTINGS_DISABLED = 2064,
+  DDS_SWITCHED = 2065,
+  FORBIDDEN_APN_NAME = 2066,
+  DDS_SWITCH_IN_PROGRESS = 2067,
+  CALL_DISALLOWED_IN_ROAMING = 2068,
+  NON_IP_NOT_SUPPORTED = 2069,
+  PDN_NON_IP_CALL_THROTTLED = 2070,
+  PDN_NON_IP_CALL_DISALLOWED = 2071,
+  CDMA_LOCK = 2072,
+  CDMA_INTERCEPT = 2073,
+  CDMA_REORDER = 2074,
+  CDMA_RELEASE_DUE_TO_SO_REJECTION = 2075,
+  CDMA_INCOMING_CALL = 2076,
+  CDMA_ALERT_STOP = 2077,
+  CHANNEL_ACQUISITION_FAILURE = 2078,
+  MAX_ACCESS_PROBE = 2079,
+  CONCURRENT_SERVICE_NOT_SUPPORTED_BY_BASE_STATION = 2080,
+  NO_RESPONSE_FROM_BASE_STATION = 2081,
+  REJECTED_BY_BASE_STATION = 2082,
+  CONCURRENT_SERVICES_INCOMPATIBLE = 2083,
+  NO_CDMA_SERVICE = 2084,
+  RUIM_NOT_PRESENT = 2085,
+  CDMA_RETRY_ORDER = 2086,
+  ACCESS_BLOCK = 2087,
+  ACCESS_BLOCK_ALL = 2088,
+  IS707B_MAX_ACCESS_PROBES = 2089,
+  THERMAL_EMERGENCY = 2090,
+  CONCURRENT_SERVICES_NOT_ALLOWED = 2091,
+  INCOMING_CALL_REJECTED = 2092,
+  NO_SERVICE_ON_GATEWAY = 2093,
+  NO_GPRS_CONTEXT = 2094,
+  ILLEGAL_MS = 2095,
+  ILLEGAL_ME = 2096,
+  GPRS_SERVICES_AND_NON_GPRS_SERVICES_NOT_ALLOWED = 2097,
+  GPRS_SERVICES_NOT_ALLOWED = 2098,
+  MS_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK = 2099,
+  IMPLICITLY_DETACHED = 2100,
+  PLMN_NOT_ALLOWED = 2101,
+  LOCATION_AREA_NOT_ALLOWED = 2102,
+  GPRS_SERVICES_NOT_ALLOWED_IN_THIS_PLMN = 2103,
+  PDP_DUPLICATE = 2104,
+  UE_RAT_CHANGE = 2105,
+  CONGESTION = 2106,
+  NO_PDP_CONTEXT_ACTIVATED = 2107,
+  ACCESS_CLASS_DSAC_REJECTION = 2108,
+  PDP_ACTIVATE_MAX_RETRY_FAILED = 2109,
+  RADIO_ACCESS_BEARER_FAILURE = 2110,
+  ESM_UNKNOWN_EPS_BEARER_CONTEXT = 2111,
+  DRB_RELEASED_BY_RRC = 2112,
+  CONNECTION_RELEASED = 2113,
+  EMM_DETACHED = 2114,
+  EMM_ATTACH_FAILED = 2115,
+  EMM_ATTACH_STARTED = 2116,
+  LTE_NAS_SERVICE_REQUEST_FAILED = 2117,
+  DUPLICATE_BEARER_ID = 2118,
+  ESM_COLLISION_SCENARIOS = 2119,
+  ESM_BEARER_DEACTIVATED_TO_SYNC_WITH_NETWORK = 2120,
+  ESM_NW_ACTIVATED_DED_BEARER_WITH_ID_OF_DEF_BEARER = 2121,
+  ESM_BAD_OTA_MESSAGE = 2122,
+  ESM_DOWNLOAD_SERVER_REJECTED_THE_CALL = 2123,
+  ESM_CONTEXT_TRANSFERRED_DUE_TO_IRAT = 2124,
+  DS_EXPLICIT_DEACTIVATION = 2125,
+  ESM_LOCAL_CAUSE_NONE = 2126,
+  LTE_THROTTLING_NOT_REQUIRED = 2127,
+  ACCESS_CONTROL_LIST_CHECK_FAILURE = 2128,
+  SERVICE_NOT_ALLOWED_ON_PLMN = 2129,
+  EMM_T3417_EXPIRED = 2130,
+  EMM_T3417_EXT_EXPIRED = 2131,
+  RRC_UPLINK_DATA_TRANSMISSION_FAILURE = 2132,
+  RRC_UPLINK_DELIVERY_FAILED_DUE_TO_HANDOVER = 2133,
+  RRC_UPLINK_CONNECTION_RELEASE = 2134,
+  RRC_UPLINK_RADIO_LINK_FAILURE = 2135,
+  RRC_UPLINK_ERROR_REQUEST_FROM_NAS = 2136,
+  RRC_CONNECTION_ACCESS_STRATUM_FAILURE = 2137,
+  RRC_CONNECTION_ANOTHER_PROCEDURE_IN_PROGRESS = 2138,
+  RRC_CONNECTION_ACCESS_BARRED = 2139,
+  RRC_CONNECTION_CELL_RESELECTION = 2140,
+  RRC_CONNECTION_CONFIG_FAILURE = 2141,
+  RRC_CONNECTION_TIMER_EXPIRED = 2142,
+  RRC_CONNECTION_LINK_FAILURE = 2143,
+  RRC_CONNECTION_CELL_NOT_CAMPED = 2144,
+  RRC_CONNECTION_SYSTEM_INTERVAL_FAILURE = 2145,
+  RRC_CONNECTION_REJECT_BY_NETWORK = 2146,
+  RRC_CONNECTION_NORMAL_RELEASE = 2147,
+  RRC_CONNECTION_RADIO_LINK_FAILURE = 2148,
+  RRC_CONNECTION_REESTABLISHMENT_FAILURE = 2149,
+  RRC_CONNECTION_OUT_OF_SERVICE_DURING_CELL_REGISTER = 2150,
+  RRC_CONNECTION_ABORT_REQUEST = 2151,
+  RRC_CONNECTION_SYSTEM_INFORMATION_BLOCK_READ_ERROR = 2152,
+  NETWORK_INITIATED_DETACH_WITH_AUTO_REATTACH = 2153,
+  NETWORK_INITIATED_DETACH_NO_AUTO_REATTACH = 2154,
+  ESM_PROCEDURE_TIME_OUT = 2155,
+  INVALID_CONNECTION_ID = 2156,
+  MAXIMIUM_NSAPIS_EXCEEDED = 2157,
+  INVALID_PRIMARY_NSAPI = 2158,
+  CANNOT_ENCODE_OTA_MESSAGE = 2159,
+  RADIO_ACCESS_BEARER_SETUP_FAILURE = 2160,
+  PDP_ESTABLISH_TIMEOUT_EXPIRED = 2161,
+  PDP_MODIFY_TIMEOUT_EXPIRED = 2162,
+  PDP_INACTIVE_TIMEOUT_EXPIRED = 2163,
+  PDP_LOWERLAYER_ERROR = 2164,
+  PDP_MODIFY_COLLISION = 2165,
+  MAXINUM_SIZE_OF_L2_MESSAGE_EXCEEDED = 2166,
+  NAS_REQUEST_REJECTED_BY_NETWORK = 2167,
+  RRC_CONNECTION_INVALID_REQUEST = 2168,
+  RRC_CONNECTION_TRACKING_AREA_ID_CHANGED = 2169,
+  RRC_CONNECTION_RF_UNAVAILABLE = 2170,
+  RRC_CONNECTION_ABORTED_DUE_TO_IRAT_CHANGE = 2171,
+  RRC_CONNECTION_RELEASED_SECURITY_NOT_ACTIVE = 2172,
+  RRC_CONNECTION_ABORTED_AFTER_HANDOVER = 2173,
+  RRC_CONNECTION_ABORTED_AFTER_IRAT_CELL_CHANGE = 2174,
+  RRC_CONNECTION_ABORTED_DURING_IRAT_CELL_CHANGE = 2175,
+  IMSI_UNKNOWN_IN_HOME_SUBSCRIBER_SERVER = 2176,
+  IMEI_NOT_ACCEPTED = 2177,
+  EPS_SERVICES_AND_NON_EPS_SERVICES_NOT_ALLOWED = 2178,
+  EPS_SERVICES_NOT_ALLOWED_IN_PLMN = 2179,
+  MSC_TEMPORARILY_NOT_REACHABLE = 2180,
+  CS_DOMAIN_NOT_AVAILABLE = 2181,
+  ESM_FAILURE = 2182,
+  MAC_FAILURE = 2183,
+  SYNCHRONIZATION_FAILURE = 2184,
+  UE_SECURITY_CAPABILITIES_MISMATCH = 2185,
+  SECURITY_MODE_REJECTED = 2186,
+  UNACCEPTABLE_NON_EPS_AUTHENTICATION = 2187,
+  CS_FALLBACK_CALL_ESTABLISHMENT_NOT_ALLOWED = 2188,
+  NO_EPS_BEARER_CONTEXT_ACTIVATED = 2189,
+  INVALID_EMM_STATE = 2190,
+  NAS_LAYER_FAILURE = 2191,
+  MULTIPLE_PDP_CALL_NOT_ALLOWED = 2192,
+  EMBMS_NOT_ENABLED = 2193,
+  IRAT_HANDOVER_FAILED = 2194,
+  EMBMS_REGULAR_DEACTIVATION = 2195,
+  TEST_LOOPBACK_REGULAR_DEACTIVATION = 2196,
+  LOWER_LAYER_REGISTRATION_FAILURE = 2197,
+  DATA_PLAN_EXPIRED = 2198,
+  UMTS_HANDOVER_TO_IWLAN = 2199,
+  EVDO_CONNECTION_DENY_BY_GENERAL_OR_NETWORK_BUSY = 2200,
+  EVDO_CONNECTION_DENY_BY_BILLING_OR_AUTHENTICATION_FAILURE = 2201,
+  EVDO_HDR_CHANGED = 2202,
+  EVDO_HDR_EXITED = 2203,
+  EVDO_HDR_NO_SESSION = 2204,
+  EVDO_USING_GPS_FIX_INSTEAD_OF_HDR_CALL = 2205,
+  EVDO_HDR_CONNECTION_SETUP_TIMEOUT = 2206,
+  FAILED_TO_ACQUIRE_COLOCATED_HDR = 2207,
+  OTASP_COMMIT_IN_PROGRESS = 2208,
+  NO_HYBRID_HDR_SERVICE = 2209,
+  HDR_NO_LOCK_GRANTED = 2210,
+  DBM_OR_SMS_IN_PROGRESS = 2211,
+  HDR_FADE = 2212,
+  HDR_ACCESS_FAILURE = 2213,
+  UNSUPPORTED_1X_PREV = 2214,
+  LOCAL_END = 2215,
+  NO_SERVICE = 2216,
+  FADE = 2217,
+  NORMAL_RELEASE = 2218,
+  ACCESS_ATTEMPT_ALREADY_IN_PROGRESS = 2219,
+  REDIRECTION_OR_HANDOFF_IN_PROGRESS = 2220,
+  EMERGENCY_MODE = 2221,
+  PHONE_IN_USE = 2222,
+  INVALID_MODE = 2223,
+  INVALID_SIM_STATE = 2224,
+  NO_COLLOCATED_HDR = 2225,
+  UE_IS_ENTERING_POWERSAVE_MODE = 2226,
+  DUAL_SWITCH = 2227,
+  PPP_TIMEOUT = 2228,
+  PPP_AUTH_FAILURE = 2229,
+  PPP_OPTION_MISMATCH = 2230,
+  PPP_PAP_FAILURE = 2231,
+  PPP_CHAP_FAILURE = 2232,
+  PPP_CLOSE_IN_PROGRESS = 2233,
+  LIMITED_TO_IPV4 = 2234,
+  LIMITED_TO_IPV6 = 2235,
+  VSNCP_TIMEOUT = 2236,
+  VSNCP_GEN_ERROR = 2237,
+  VSNCP_APN_UNAUTHORIZED = 2238,
+  VSNCP_PDN_LIMIT_EXCEEDED = 2239,
+  VSNCP_NO_PDN_GATEWAY_ADDRESS = 2240,
+  VSNCP_PDN_GATEWAY_UNREACHABLE = 2241,
+  VSNCP_PDN_GATEWAY_REJECT = 2242,
+  VSNCP_INSUFFICIENT_PARAMETERS = 2243,
+  VSNCP_RESOURCE_UNAVAILABLE = 2244,
+  VSNCP_ADMINISTRATIVELY_PROHIBITED = 2245,
+  VSNCP_PDN_ID_IN_USE = 2246,
+  VSNCP_SUBSCRIBER_LIMITATION = 2247,
+  VSNCP_PDN_EXISTS_FOR_THIS_APN = 2248,
+  VSNCP_RECONNECT_NOT_ALLOWED = 2249,
+  IPV6_PREFIX_UNAVAILABLE = 2250,
+  HANDOFF_PREFERENCE_CHANGED = 2251,
+  SLICE_REJECTED = 2252,
+  MATCH_ALL_RULE_NOT_ALLOWED = 2253,
+  ALL_MATCHING_RULES_FAILED = 2254,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataProfileInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataProfileInfo.aidl
new file mode 100644
index 0000000..16fada1
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataProfileInfo.aidl
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.data;
+@JavaDerive(toString=true) @VintfStability
+parcelable DataProfileInfo {
+  int profileId;
+  String apn;
+  android.hardware.radio.data.PdpProtocolType protocol;
+  android.hardware.radio.data.PdpProtocolType roamingProtocol;
+  android.hardware.radio.data.ApnAuthType authType;
+  String user;
+  String password;
+  int type;
+  int maxConnsTime;
+  int maxConns;
+  int waitTime;
+  boolean enabled;
+  int supportedApnTypesBitmap;
+  int bearerBitmap;
+  int mtuV4;
+  int mtuV6;
+  boolean preferred;
+  boolean persistent;
+  boolean alwaysOn;
+  android.hardware.radio.data.TrafficDescriptor trafficDescriptor;
+  const int ID_DEFAULT = 0;
+  const int ID_TETHERED = 1;
+  const int ID_IMS = 2;
+  const int ID_FOTA = 3;
+  const int ID_CBS = 4;
+  const int ID_OEM_BASE = 1000;
+  const int ID_INVALID = -1;
+  const int TYPE_COMMON = 0;
+  const int TYPE_3GPP = 1;
+  const int TYPE_3GPP2 = 2;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataRequestReason.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataRequestReason.aidl
new file mode 100644
index 0000000..0ddaff1
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataRequestReason.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.data;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum DataRequestReason {
+  NORMAL = 1,
+  SHUTDOWN = 2,
+  HANDOVER = 3,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataThrottlingAction.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataThrottlingAction.aidl
new file mode 100644
index 0000000..4f976cd
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataThrottlingAction.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.data;
+@Backing(type="byte") @JavaDerive(toString=true) @VintfStability
+enum DataThrottlingAction {
+  NO_DATA_THROTTLING = 0,
+  THROTTLE_SECONDARY_CARRIER = 1,
+  THROTTLE_ANCHOR_CARRIER = 2,
+  HOLD = 3,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/EpsQos.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/EpsQos.aidl
new file mode 100644
index 0000000..5b9aaa0
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/EpsQos.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.data;
+@JavaDerive(toString=true) @VintfStability
+parcelable EpsQos {
+  int qci;
+  android.hardware.radio.data.QosBandwidth downlink;
+  android.hardware.radio.data.QosBandwidth uplink;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioData.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioData.aidl
new file mode 100644
index 0000000..7b572f1
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioData.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.data;
+@VintfStability
+interface IRadioData {
+  oneway void allocatePduSessionId(in int serial);
+  oneway void cancelHandover(in int serial, in int callId);
+  oneway void deactivateDataCall(in int serial, in int cid, in android.hardware.radio.data.DataRequestReason reason);
+  oneway void getDataCallList(in int serial);
+  oneway void getSlicingConfig(in int serial);
+  oneway void releasePduSessionId(in int serial, in int id);
+  oneway void responseAcknowledgement();
+  oneway void setDataAllowed(in int serial, in boolean allow);
+  oneway void setDataProfile(in int serial, in android.hardware.radio.data.DataProfileInfo[] profiles);
+  oneway void setDataThrottling(in int serial, in android.hardware.radio.data.DataThrottlingAction dataThrottlingAction, in long completionDurationMillis);
+  oneway void setInitialAttachApn(in int serial, in @nullable android.hardware.radio.data.DataProfileInfo dataProfileInfo);
+  oneway void setResponseFunctions(in android.hardware.radio.data.IRadioDataResponse radioDataResponse, in android.hardware.radio.data.IRadioDataIndication radioDataIndication);
+  oneway void setupDataCall(in int serial, in android.hardware.radio.AccessNetwork accessNetwork, in android.hardware.radio.data.DataProfileInfo dataProfileInfo, in boolean roamingAllowed, in android.hardware.radio.data.DataRequestReason reason, in android.hardware.radio.data.LinkAddress[] addresses, in String[] dnses, in int pduSessionId, in @nullable android.hardware.radio.data.SliceInfo sliceInfo, in boolean matchAllRuleAllowed);
+  oneway void startHandover(in int serial, in int callId);
+  oneway void startKeepalive(in int serial, in android.hardware.radio.data.KeepaliveRequest keepalive);
+  oneway void stopKeepalive(in int serial, in int sessionHandle);
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioDataIndication.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioDataIndication.aidl
new file mode 100644
index 0000000..0ffa1f7
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioDataIndication.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.data;
+@VintfStability
+interface IRadioDataIndication {
+  oneway void dataCallListChanged(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.data.SetupDataCallResult[] dcList);
+  oneway void keepaliveStatus(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.data.KeepaliveStatus status);
+  oneway void pcoData(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.data.PcoDataInfo pco);
+  oneway void unthrottleApn(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.data.DataProfileInfo dataProfileInfo);
+  oneway void slicingConfigChanged(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.data.SlicingConfig slicingConfig);
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioDataResponse.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioDataResponse.aidl
new file mode 100644
index 0000000..4edc17d
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/IRadioDataResponse.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.data;
+@VintfStability
+interface IRadioDataResponse {
+  oneway void acknowledgeRequest(in int serial);
+  oneway void allocatePduSessionIdResponse(in android.hardware.radio.RadioResponseInfo info, in int id);
+  oneway void cancelHandoverResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void deactivateDataCallResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void getDataCallListResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.data.SetupDataCallResult[] dcResponse);
+  oneway void getSlicingConfigResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.data.SlicingConfig slicingConfig);
+  oneway void releasePduSessionIdResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setDataAllowedResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setDataProfileResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setDataThrottlingResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setInitialAttachApnResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setupDataCallResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.data.SetupDataCallResult dcResponse);
+  oneway void startHandoverResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void startKeepaliveResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.data.KeepaliveStatus status);
+  oneway void stopKeepaliveResponse(in android.hardware.radio.RadioResponseInfo info);
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/KeepaliveRequest.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/KeepaliveRequest.aidl
new file mode 100644
index 0000000..592a54a
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/KeepaliveRequest.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.data;
+@JavaDerive(toString=true) @VintfStability
+parcelable KeepaliveRequest {
+  int type;
+  byte[] sourceAddress;
+  int sourcePort;
+  byte[] destinationAddress;
+  int destinationPort;
+  int maxKeepaliveIntervalMillis;
+  int cid;
+  const int TYPE_NATT_IPV4 = 0;
+  const int TYPE_NATT_IPV6 = 1;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/KeepaliveStatus.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/KeepaliveStatus.aidl
new file mode 100644
index 0000000..82b0fc8
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/KeepaliveStatus.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.data;
+@JavaDerive(toString=true) @VintfStability
+parcelable KeepaliveStatus {
+  int sessionHandle;
+  int code;
+  const int CODE_ACTIVE = 0;
+  const int CODE_INACTIVE = 1;
+  const int CODE_PENDING = 2;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/LinkAddress.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/LinkAddress.aidl
new file mode 100644
index 0000000..48e646e
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/LinkAddress.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.data;
+@JavaDerive(toString=true) @VintfStability
+parcelable LinkAddress {
+  String address;
+  int addressProperties;
+  long deprecationTime;
+  long expirationTime;
+  const int ADDRESS_PROPERTY_NONE = 0;
+  const int ADDRESS_PROPERTY_DEPRECATED = 32;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/NrQos.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/NrQos.aidl
new file mode 100644
index 0000000..62f6204
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/NrQos.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.data;
+@JavaDerive(toString=true) @VintfStability
+parcelable NrQos {
+  int fiveQi;
+  android.hardware.radio.data.QosBandwidth downlink;
+  android.hardware.radio.data.QosBandwidth uplink;
+  byte qfi;
+  char averagingWindowMs;
+  const byte FLOW_ID_RANGE_MIN = 1;
+  const byte FLOW_ID_RANGE_MAX = 63;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/OsAppId.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/OsAppId.aidl
new file mode 100644
index 0000000..8595d52
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/OsAppId.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.data;
+@JavaDerive(toString=true) @VintfStability
+parcelable OsAppId {
+  byte[] osAppId;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/PcoDataInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/PcoDataInfo.aidl
new file mode 100644
index 0000000..033b12f
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/PcoDataInfo.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.data;
+@JavaDerive(toString=true) @VintfStability
+parcelable PcoDataInfo {
+  int cid;
+  String bearerProto;
+  int pcoId;
+  byte[] contents;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/PdpProtocolType.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/PdpProtocolType.aidl
new file mode 100644
index 0000000..9771e5c
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/PdpProtocolType.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.data;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum PdpProtocolType {
+  UNKNOWN = -1,
+  IP = 0,
+  IPV6 = 1,
+  IPV4V6 = 2,
+  PPP = 3,
+  NON_IP = 4,
+  UNSTRUCTURED = 5,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/PortRange.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/PortRange.aidl
new file mode 100644
index 0000000..470a9c1
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/PortRange.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.data;
+@JavaDerive(toString=true) @VintfStability
+parcelable PortRange {
+  int start;
+  int end;
+  const int PORT_RANGE_MIN = 20;
+  const int PORT_RANGE_MAX = 65535;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/Qos.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/Qos.aidl
new file mode 100644
index 0000000..ca06e41
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/Qos.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.data;
+@JavaDerive(toString=true) @VintfStability
+union Qos {
+  boolean noinit;
+  android.hardware.radio.data.EpsQos eps;
+  android.hardware.radio.data.NrQos nr;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosBandwidth.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosBandwidth.aidl
new file mode 100644
index 0000000..6d4b7a9
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosBandwidth.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.data;
+@JavaDerive(toString=true) @VintfStability
+parcelable QosBandwidth {
+  int maxBitrateKbps;
+  int guaranteedBitrateKbps;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosFilter.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosFilter.aidl
new file mode 100644
index 0000000..e22b359
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosFilter.aidl
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.data;
+@JavaDerive(toString=true) @VintfStability
+parcelable QosFilter {
+  String[] localAddresses;
+  String[] remoteAddresses;
+  @nullable android.hardware.radio.data.PortRange localPort;
+  @nullable android.hardware.radio.data.PortRange remotePort;
+  byte protocol;
+  android.hardware.radio.data.QosFilterTypeOfService tos;
+  android.hardware.radio.data.QosFilterIpv6FlowLabel flowLabel;
+  android.hardware.radio.data.QosFilterIpsecSpi spi;
+  byte direction;
+  int precedence;
+  const byte DIRECTION_DOWNLINK = 0;
+  const byte DIRECTION_UPLINK = 1;
+  const byte DIRECTION_BIDIRECTIONAL = 2;
+  const byte PROTOCOL_UNSPECIFIED = -1;
+  const byte PROTOCOL_TCP = 6;
+  const byte PROTOCOL_UDP = 17;
+  const byte PROTOCOL_ESP = 50;
+  const byte PROTOCOL_AH = 51;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosFilterIpsecSpi.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosFilterIpsecSpi.aidl
new file mode 100644
index 0000000..4b75340
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosFilterIpsecSpi.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.data;
+@JavaDerive(toString=true) @VintfStability
+union QosFilterIpsecSpi {
+  boolean noinit;
+  int value;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosFilterIpv6FlowLabel.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosFilterIpv6FlowLabel.aidl
new file mode 100644
index 0000000..3fb34ea
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosFilterIpv6FlowLabel.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.data;
+@JavaDerive(toString=true) @VintfStability
+union QosFilterIpv6FlowLabel {
+  boolean noinit;
+  int value;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosFilterTypeOfService.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosFilterTypeOfService.aidl
new file mode 100644
index 0000000..fa85b5a
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosFilterTypeOfService.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.data;
+@JavaDerive(toString=true) @VintfStability
+union QosFilterTypeOfService {
+  boolean noinit;
+  byte value;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosSession.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosSession.aidl
new file mode 100644
index 0000000..bbfdd2d
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/QosSession.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.data;
+@JavaDerive(toString=true) @VintfStability
+parcelable QosSession {
+  int qosSessionId;
+  android.hardware.radio.data.Qos qos;
+  android.hardware.radio.data.QosFilter[] qosFilters;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/RouteSelectionDescriptor.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/RouteSelectionDescriptor.aidl
new file mode 100644
index 0000000..434ee7d
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/RouteSelectionDescriptor.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.data;
+@JavaDerive(toString=true) @VintfStability
+parcelable RouteSelectionDescriptor {
+  byte precedence;
+  android.hardware.radio.data.PdpProtocolType sessionType;
+  byte sscMode;
+  android.hardware.radio.data.SliceInfo[] sliceInfo;
+  String[] dnn;
+  const byte SSC_MODE_UNKNOWN = -1;
+  const byte SSC_MODE_1 = 1;
+  const byte SSC_MODE_2 = 2;
+  const byte SSC_MODE_3 = 3;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/SetupDataCallResult.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/SetupDataCallResult.aidl
new file mode 100644
index 0000000..83f9db6
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/SetupDataCallResult.aidl
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.data;
+@JavaDerive(toString=true) @VintfStability
+parcelable SetupDataCallResult {
+  android.hardware.radio.data.DataCallFailCause cause;
+  long suggestedRetryTime;
+  int cid;
+  int active;
+  android.hardware.radio.data.PdpProtocolType type;
+  String ifname;
+  android.hardware.radio.data.LinkAddress[] addresses;
+  String[] dnses;
+  String[] gateways;
+  String[] pcscf;
+  int mtuV4;
+  int mtuV6;
+  android.hardware.radio.data.Qos defaultQos;
+  android.hardware.radio.data.QosSession[] qosSessions;
+  byte handoverFailureMode;
+  int pduSessionId;
+  @nullable android.hardware.radio.data.SliceInfo sliceInfo;
+  android.hardware.radio.data.TrafficDescriptor[] trafficDescriptors;
+  const int DATA_CONNECTION_STATUS_INACTIVE = 0;
+  const int DATA_CONNECTION_STATUS_DORMANT = 1;
+  const int DATA_CONNECTION_STATUS_ACTIVE = 2;
+  const byte HANDOVER_FAILURE_MODE_LEGACY = 0;
+  const byte HANDOVER_FAILURE_MODE_DO_FALLBACK = 1;
+  const byte HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_HANDOVER = 2;
+  const byte HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_SETUP_NORMAL = 3;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/SliceInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/SliceInfo.aidl
new file mode 100644
index 0000000..efe4816
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/SliceInfo.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.data;
+@JavaDerive(toString=true) @VintfStability
+parcelable SliceInfo {
+  byte sliceServiceType;
+  int sliceDifferentiator;
+  byte mappedHplmnSst;
+  int mappedHplmnSd;
+  byte status;
+  const byte SERVICE_TYPE_NONE = 0;
+  const byte SERVICE_TYPE_EMBB = 1;
+  const byte SERVICE_TYPE_URLLC = 2;
+  const byte SERVICE_TYPE_MIOT = 3;
+  const byte STATUS_UNKNOWN = 0;
+  const byte STATUS_CONFIGURED = 1;
+  const byte STATUS_ALLOWED = 2;
+  const byte STATUS_REJECTED_NOT_AVAILABLE_IN_PLMN = 3;
+  const byte STATUS_REJECTED_NOT_AVAILABLE_IN_REG_AREA = 4;
+  const byte STATUS_DEFAULT_CONFIGURED = 5;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/SlicingConfig.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/SlicingConfig.aidl
new file mode 100644
index 0000000..b00febe
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/SlicingConfig.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.data;
+@JavaDerive(toString=true) @VintfStability
+parcelable SlicingConfig {
+  android.hardware.radio.data.UrspRule[] urspRules;
+  android.hardware.radio.data.SliceInfo[] sliceInfo;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/TrafficDescriptor.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/TrafficDescriptor.aidl
new file mode 100644
index 0000000..d7b0654
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/TrafficDescriptor.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.data;
+@JavaDerive(toString=true) @VintfStability
+parcelable TrafficDescriptor {
+  @nullable String dnn;
+  @nullable android.hardware.radio.data.OsAppId osAppId;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/UrspRule.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/UrspRule.aidl
new file mode 100644
index 0000000..7002fd1
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/UrspRule.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.data;
+@JavaDerive(toString=true) @VintfStability
+parcelable UrspRule {
+  int precedence;
+  android.hardware.radio.data.TrafficDescriptor[] trafficDescriptors;
+  android.hardware.radio.data.RouteSelectionDescriptor[] routeSelectionDescriptor;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaBroadcastSmsConfigInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaBroadcastSmsConfigInfo.aidl
new file mode 100644
index 0000000..39e2be2
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaBroadcastSmsConfigInfo.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.messaging;
+@JavaDerive(toString=true) @VintfStability
+parcelable CdmaBroadcastSmsConfigInfo {
+  int serviceCategory;
+  int language;
+  boolean selected;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsAck.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsAck.aidl
new file mode 100644
index 0000000..befdbde
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsAck.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.messaging;
+@JavaDerive(toString=true) @VintfStability
+parcelable CdmaSmsAck {
+  boolean errorClass;
+  int smsCauseCode;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsAddress.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsAddress.aidl
new file mode 100644
index 0000000..ab29c77
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsAddress.aidl
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.messaging;
+@JavaDerive(toString=true) @VintfStability
+parcelable CdmaSmsAddress {
+  int digitMode;
+  boolean isNumberModeDataNetwork;
+  int numberType;
+  int numberPlan;
+  byte[] digits;
+  const int DIGIT_MODE_FOUR_BIT = 0;
+  const int DIGIT_MODE_EIGHT_BIT = 1;
+  const int NUMBER_PLAN_UNKNOWN = 0;
+  const int NUMBER_PLAN_TELEPHONY = 1;
+  const int NUMBER_PLAN_RESERVED_2 = 2;
+  const int NUMBER_PLAN_DATA = 3;
+  const int NUMBER_PLAN_TELEX = 4;
+  const int NUMBER_PLAN_RESERVED_5 = 5;
+  const int NUMBER_PLAN_RESERVED_6 = 6;
+  const int NUMBER_PLAN_RESERVED_7 = 7;
+  const int NUMBER_PLAN_RESERVED_8 = 8;
+  const int NUMBER_PLAN_PRIVATE = 9;
+  const int NUMBER_PLAN_RESERVED_10 = 10;
+  const int NUMBER_PLAN_RESERVED_11 = 11;
+  const int NUMBER_PLAN_RESERVED_12 = 12;
+  const int NUMBER_PLAN_RESERVED_13 = 13;
+  const int NUMBER_PLAN_RESERVED_14 = 14;
+  const int NUMBER_PLAN_RESERVED_15 = 15;
+  const int NUMBER_TYPE_UNKNOWN = 0;
+  const int NUMBER_TYPE_INTERNATIONAL_OR_DATA_IP = 1;
+  const int NUMBER_TYPE_NATIONAL_OR_INTERNET_MAIL = 2;
+  const int NUMBER_TYPE_NETWORK = 3;
+  const int NUMBER_TYPE_SUBSCRIBER = 4;
+  const int NUMBER_TYPE_ALPHANUMERIC = 5;
+  const int NUMBER_TYPE_ABBREVIATED = 6;
+  const int NUMBER_TYPE_RESERVED_7 = 7;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsMessage.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsMessage.aidl
new file mode 100644
index 0000000..867596c
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsMessage.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.messaging;
+@JavaDerive(toString=true) @VintfStability
+parcelable CdmaSmsMessage {
+  int teleserviceId;
+  boolean isServicePresent;
+  int serviceCategory;
+  android.hardware.radio.messaging.CdmaSmsAddress address;
+  android.hardware.radio.messaging.CdmaSmsSubaddress subAddress;
+  byte[] bearerData;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsSubaddress.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsSubaddress.aidl
new file mode 100644
index 0000000..d67fe8c
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsSubaddress.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.messaging;
+@JavaDerive(toString=true) @VintfStability
+parcelable CdmaSmsSubaddress {
+  int subaddressType;
+  boolean odd;
+  byte[] digits;
+  const int SUBADDRESS_TYPE_NSAP = 0;
+  const int SUBADDRESS_TYPE_USER_SPECIFIED = 1;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsWriteArgs.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsWriteArgs.aidl
new file mode 100644
index 0000000..b0a7f98
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/CdmaSmsWriteArgs.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.messaging;
+@JavaDerive(toString=true) @VintfStability
+parcelable CdmaSmsWriteArgs {
+  int status;
+  android.hardware.radio.messaging.CdmaSmsMessage message;
+  const int STATUS_REC_UNREAD = 0;
+  const int STATUS_REC_READ = 1;
+  const int STATUS_STO_UNSENT = 2;
+  const int STATUS_STO_SENT = 3;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/GsmBroadcastSmsConfigInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/GsmBroadcastSmsConfigInfo.aidl
new file mode 100644
index 0000000..46604ca
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/GsmBroadcastSmsConfigInfo.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.messaging;
+@JavaDerive(toString=true) @VintfStability
+parcelable GsmBroadcastSmsConfigInfo {
+  int fromServiceId;
+  int toServiceId;
+  int fromCodeScheme;
+  int toCodeScheme;
+  boolean selected;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/GsmSmsMessage.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/GsmSmsMessage.aidl
new file mode 100644
index 0000000..4df7fd2
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/GsmSmsMessage.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.messaging;
+@JavaDerive(toString=true) @VintfStability
+parcelable GsmSmsMessage {
+  String smscPdu;
+  String pdu;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessaging.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessaging.aidl
new file mode 100644
index 0000000..dfec59a
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessaging.aidl
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.messaging;
+@VintfStability
+interface IRadioMessaging {
+  oneway void acknowledgeIncomingGsmSmsWithPdu(in int serial, in boolean success, in String ackPdu);
+  oneway void acknowledgeLastIncomingCdmaSms(in int serial, in android.hardware.radio.messaging.CdmaSmsAck smsAck);
+  oneway void acknowledgeLastIncomingGsmSms(in int serial, in boolean success, in android.hardware.radio.messaging.SmsAcknowledgeFailCause cause);
+  oneway void deleteSmsOnRuim(in int serial, in int index);
+  oneway void deleteSmsOnSim(in int serial, in int index);
+  oneway void getCdmaBroadcastConfig(in int serial);
+  oneway void getGsmBroadcastConfig(in int serial);
+  oneway void getSmscAddress(in int serial);
+  oneway void reportSmsMemoryStatus(in int serial, in boolean available);
+  oneway void responseAcknowledgement();
+  oneway void sendCdmaSms(in int serial, in android.hardware.radio.messaging.CdmaSmsMessage sms);
+  oneway void sendCdmaSmsExpectMore(in int serial, in android.hardware.radio.messaging.CdmaSmsMessage sms);
+  oneway void sendImsSms(in int serial, in android.hardware.radio.messaging.ImsSmsMessage message);
+  oneway void sendSms(in int serial, in android.hardware.radio.messaging.GsmSmsMessage message);
+  oneway void sendSmsExpectMore(in int serial, in android.hardware.radio.messaging.GsmSmsMessage message);
+  oneway void setCdmaBroadcastActivation(in int serial, in boolean activate);
+  oneway void setCdmaBroadcastConfig(in int serial, in android.hardware.radio.messaging.CdmaBroadcastSmsConfigInfo[] configInfo);
+  oneway void setGsmBroadcastActivation(in int serial, in boolean activate);
+  oneway void setGsmBroadcastConfig(in int serial, in android.hardware.radio.messaging.GsmBroadcastSmsConfigInfo[] configInfo);
+  oneway void setResponseFunctions(in android.hardware.radio.messaging.IRadioMessagingResponse radioMessagingResponse, in android.hardware.radio.messaging.IRadioMessagingIndication radioMessagingIndication);
+  oneway void setSmscAddress(in int serial, in String smsc);
+  oneway void writeSmsToRuim(in int serial, in android.hardware.radio.messaging.CdmaSmsWriteArgs cdmaSms);
+  oneway void writeSmsToSim(in int serial, in android.hardware.radio.messaging.SmsWriteArgs smsWriteArgs);
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessagingIndication.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessagingIndication.aidl
new file mode 100644
index 0000000..8f7824f
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessagingIndication.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.messaging;
+@VintfStability
+interface IRadioMessagingIndication {
+  oneway void cdmaNewSms(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.messaging.CdmaSmsMessage msg);
+  oneway void cdmaRuimSmsStorageFull(in android.hardware.radio.RadioIndicationType type);
+  oneway void newBroadcastSms(in android.hardware.radio.RadioIndicationType type, in byte[] data);
+  oneway void newSms(in android.hardware.radio.RadioIndicationType type, in byte[] pdu);
+  oneway void newSmsOnSim(in android.hardware.radio.RadioIndicationType type, in int recordNumber);
+  oneway void newSmsStatusReport(in android.hardware.radio.RadioIndicationType type, in byte[] pdu);
+  oneway void simSmsStorageFull(in android.hardware.radio.RadioIndicationType type);
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessagingResponse.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessagingResponse.aidl
new file mode 100644
index 0000000..c3af7a6
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/IRadioMessagingResponse.aidl
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.messaging;
+@VintfStability
+interface IRadioMessagingResponse {
+  oneway void acknowledgeIncomingGsmSmsWithPduResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void acknowledgeLastIncomingCdmaSmsResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void acknowledgeLastIncomingGsmSmsResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void acknowledgeRequest(in int serial);
+  oneway void deleteSmsOnRuimResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void deleteSmsOnSimResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void getCdmaBroadcastConfigResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.messaging.CdmaBroadcastSmsConfigInfo[] configs);
+  oneway void getGsmBroadcastConfigResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.messaging.GsmBroadcastSmsConfigInfo[] configs);
+  oneway void getSmscAddressResponse(in android.hardware.radio.RadioResponseInfo info, in String smsc);
+  oneway void reportSmsMemoryStatusResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void sendCdmaSmsExpectMoreResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.messaging.SendSmsResult sms);
+  oneway void sendCdmaSmsResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.messaging.SendSmsResult sms);
+  oneway void sendImsSmsResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.messaging.SendSmsResult sms);
+  oneway void sendSmsExpectMoreResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.messaging.SendSmsResult sms);
+  oneway void sendSmsResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.messaging.SendSmsResult sms);
+  oneway void setCdmaBroadcastActivationResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setCdmaBroadcastConfigResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setGsmBroadcastActivationResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setGsmBroadcastConfigResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setSmscAddressResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void writeSmsToRuimResponse(in android.hardware.radio.RadioResponseInfo info, in int index);
+  oneway void writeSmsToSimResponse(in android.hardware.radio.RadioResponseInfo info, in int index);
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/ImsSmsMessage.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/ImsSmsMessage.aidl
new file mode 100644
index 0000000..85f62b7
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/ImsSmsMessage.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.messaging;
+@JavaDerive(toString=true) @VintfStability
+parcelable ImsSmsMessage {
+  android.hardware.radio.RadioTechnologyFamily tech;
+  boolean retry;
+  int messageRef;
+  android.hardware.radio.messaging.CdmaSmsMessage[] cdmaMessage;
+  android.hardware.radio.messaging.GsmSmsMessage[] gsmMessage;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/SendSmsResult.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/SendSmsResult.aidl
new file mode 100644
index 0000000..32f7a5c
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/SendSmsResult.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.messaging;
+@JavaDerive(toString=true) @VintfStability
+parcelable SendSmsResult {
+  int messageRef;
+  String ackPDU;
+  int errorCode;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/SmsAcknowledgeFailCause.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/SmsAcknowledgeFailCause.aidl
new file mode 100644
index 0000000..019b185
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/SmsAcknowledgeFailCause.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.messaging;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum SmsAcknowledgeFailCause {
+  MEMORY_CAPACITY_EXCEEDED = 211,
+  UNSPECIFIED_ERROR = 255,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/SmsWriteArgs.aidl b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/SmsWriteArgs.aidl
new file mode 100644
index 0000000..489cc07
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.messaging/current/android/hardware/radio/messaging/SmsWriteArgs.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.messaging;
+@JavaDerive(toString=true) @VintfStability
+parcelable SmsWriteArgs {
+  int status;
+  String pdu;
+  String smsc;
+  const int STATUS_REC_UNREAD = 0;
+  const int STATUS_REC_READ = 1;
+  const int STATUS_STO_UNSENT = 2;
+  const int STATUS_STO_SENT = 3;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ActivityStatsInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ActivityStatsInfo.aidl
new file mode 100644
index 0000000..7e22ee0
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ActivityStatsInfo.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.modem;
+@JavaDerive(toString=true) @VintfStability
+parcelable ActivityStatsInfo {
+  int sleepModeTimeMs;
+  int idleModeTimeMs;
+  android.hardware.radio.modem.ActivityStatsTechSpecificInfo[] techSpecificInfo;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.aidl
new file mode 100644
index 0000000..08ed9a5
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.modem;
+@JavaDerive(toString=true) @VintfStability
+parcelable ActivityStatsTechSpecificInfo {
+  android.hardware.radio.AccessNetwork rat;
+  int frequencyRange;
+  int[] txmModetimeMs;
+  int rxModeTimeMs;
+  const int FREQUENCY_RANGE_UNKNOWN = 0;
+  const int FREQUENCY_RANGE_LOW = 1;
+  const int FREQUENCY_RANGE_MID = 2;
+  const int FREQUENCY_RANGE_HIGH = 3;
+  const int FREQUENCY_RANGE_MMWAVE = 4;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/DeviceStateType.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/DeviceStateType.aidl
new file mode 100644
index 0000000..4e8c6d7
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/DeviceStateType.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.modem;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum DeviceStateType {
+  POWER_SAVE_MODE = 0,
+  CHARGING_STATE = 1,
+  LOW_DATA_EXPECTED = 2,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/HardwareConfig.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/HardwareConfig.aidl
new file mode 100644
index 0000000..3a0ec25
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/HardwareConfig.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.modem;
+@JavaDerive(toString=true) @VintfStability
+parcelable HardwareConfig {
+  int type;
+  String uuid;
+  int state;
+  android.hardware.radio.modem.HardwareConfigModem[] modem;
+  android.hardware.radio.modem.HardwareConfigSim[] sim;
+  const int STATE_ENABLED = 0;
+  const int STATE_STANDBY = 1;
+  const int STATE_DISABLED = 2;
+  const int TYPE_MODEM = 0;
+  const int TYPE_SIM = 1;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/HardwareConfigModem.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/HardwareConfigModem.aidl
new file mode 100644
index 0000000..62bb160
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/HardwareConfigModem.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.modem;
+@JavaDerive(toString=true) @VintfStability
+parcelable HardwareConfigModem {
+  int rilModel;
+  android.hardware.radio.RadioTechnology rat;
+  int maxVoiceCalls;
+  int maxDataCalls;
+  int maxStandby;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/HardwareConfigSim.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/HardwareConfigSim.aidl
new file mode 100644
index 0000000..5810982
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/HardwareConfigSim.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.modem;
+@JavaDerive(toString=true) @VintfStability
+parcelable HardwareConfigSim {
+  String modemUuid;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/IRadioModem.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/IRadioModem.aidl
new file mode 100644
index 0000000..41eff51
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/IRadioModem.aidl
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.modem;
+@VintfStability
+interface IRadioModem {
+  oneway void enableModem(in int serial, in boolean on);
+  oneway void getBasebandVersion(in int serial);
+  oneway void getDeviceIdentity(in int serial);
+  oneway void getHardwareConfig(in int serial);
+  oneway void getModemActivityInfo(in int serial);
+  oneway void getModemStackStatus(in int serial);
+  oneway void getRadioCapability(in int serial);
+  oneway void nvReadItem(in int serial, in android.hardware.radio.modem.NvItem itemId);
+  oneway void nvResetConfig(in int serial, in android.hardware.radio.modem.ResetNvType resetType);
+  oneway void nvWriteCdmaPrl(in int serial, in byte[] prl);
+  oneway void nvWriteItem(in int serial, in android.hardware.radio.modem.NvWriteItem item);
+  oneway void requestShutdown(in int serial);
+  oneway void responseAcknowledgement();
+  oneway void sendDeviceState(in int serial, in android.hardware.radio.modem.DeviceStateType deviceStateType, in boolean state);
+  oneway void setRadioCapability(in int serial, in android.hardware.radio.modem.RadioCapability rc);
+  oneway void setRadioPower(in int serial, in boolean powerOn, in boolean forEmergencyCall, in boolean preferredForEmergencyCall);
+  oneway void setResponseFunctions(in android.hardware.radio.modem.IRadioModemResponse radioModemResponse, in android.hardware.radio.modem.IRadioModemIndication radioModemIndication);
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/IRadioModemIndication.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/IRadioModemIndication.aidl
new file mode 100644
index 0000000..514ff9a
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/IRadioModemIndication.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.modem;
+@VintfStability
+interface IRadioModemIndication {
+  oneway void hardwareConfigChanged(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.modem.HardwareConfig[] configs);
+  oneway void modemReset(in android.hardware.radio.RadioIndicationType type, in String reason);
+  oneway void radioCapabilityIndication(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.modem.RadioCapability rc);
+  oneway void radioStateChanged(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.modem.RadioState radioState);
+  oneway void rilConnected(in android.hardware.radio.RadioIndicationType type);
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/IRadioModemResponse.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/IRadioModemResponse.aidl
new file mode 100644
index 0000000..dcaff45
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/IRadioModemResponse.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.modem;
+@VintfStability
+interface IRadioModemResponse {
+  oneway void acknowledgeRequest(in int serial);
+  oneway void enableModemResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void getBasebandVersionResponse(in android.hardware.radio.RadioResponseInfo info, in String version);
+  oneway void getDeviceIdentityResponse(in android.hardware.radio.RadioResponseInfo info, in String imei, in String imeisv, in String esn, in String meid);
+  oneway void getHardwareConfigResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.modem.HardwareConfig[] config);
+  oneway void getModemActivityInfoResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.modem.ActivityStatsInfo activityInfo);
+  oneway void getModemStackStatusResponse(in android.hardware.radio.RadioResponseInfo info, in boolean isEnabled);
+  oneway void getRadioCapabilityResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.modem.RadioCapability rc);
+  oneway void nvReadItemResponse(in android.hardware.radio.RadioResponseInfo info, in String result);
+  oneway void nvResetConfigResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void nvWriteCdmaPrlResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void nvWriteItemResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void requestShutdownResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void sendDeviceStateResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setRadioCapabilityResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.modem.RadioCapability rc);
+  oneway void setRadioPowerResponse(in android.hardware.radio.RadioResponseInfo info);
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/NvItem.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/NvItem.aidl
new file mode 100644
index 0000000..3e27643
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/NvItem.aidl
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.modem;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum NvItem {
+  CDMA_MEID = 1,
+  CDMA_MIN = 2,
+  CDMA_MDN = 3,
+  CDMA_ACCOLC = 4,
+  DEVICE_MSL = 11,
+  RTN_RECONDITIONED_STATUS = 12,
+  RTN_ACTIVATION_DATE = 13,
+  RTN_LIFE_TIMER = 14,
+  RTN_LIFE_CALLS = 15,
+  RTN_LIFE_DATA_TX = 16,
+  RTN_LIFE_DATA_RX = 17,
+  OMADM_HFA_LEVEL = 18,
+  MIP_PROFILE_NAI = 31,
+  MIP_PROFILE_HOME_ADDRESS = 32,
+  MIP_PROFILE_AAA_AUTH = 33,
+  MIP_PROFILE_HA_AUTH = 34,
+  MIP_PROFILE_PRI_HA_ADDR = 35,
+  MIP_PROFILE_SEC_HA_ADDR = 36,
+  MIP_PROFILE_REV_TUN_PREF = 37,
+  MIP_PROFILE_HA_SPI = 38,
+  MIP_PROFILE_AAA_SPI = 39,
+  MIP_PROFILE_MN_HA_SS = 40,
+  MIP_PROFILE_MN_AAA_SS = 41,
+  CDMA_PRL_VERSION = 51,
+  CDMA_BC10 = 52,
+  CDMA_BC14 = 53,
+  CDMA_SO68 = 54,
+  CDMA_SO73_COP0 = 55,
+  CDMA_SO73_COP1TO7 = 56,
+  CDMA_1X_ADVANCED_ENABLED = 57,
+  CDMA_EHRPD_ENABLED = 58,
+  CDMA_EHRPD_FORCED = 59,
+  LTE_BAND_ENABLE_25 = 71,
+  LTE_BAND_ENABLE_26 = 72,
+  LTE_BAND_ENABLE_41 = 73,
+  LTE_SCAN_PRIORITY_25 = 74,
+  LTE_SCAN_PRIORITY_26 = 75,
+  LTE_SCAN_PRIORITY_41 = 76,
+  LTE_HIDDEN_BAND_PRIORITY_25 = 77,
+  LTE_HIDDEN_BAND_PRIORITY_26 = 78,
+  LTE_HIDDEN_BAND_PRIORITY_41 = 79,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/NvWriteItem.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/NvWriteItem.aidl
new file mode 100644
index 0000000..17b7de0
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/NvWriteItem.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.modem;
+@JavaDerive(toString=true) @VintfStability
+parcelable NvWriteItem {
+  android.hardware.radio.modem.NvItem itemId;
+  String value;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/RadioCapability.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/RadioCapability.aidl
new file mode 100644
index 0000000..f2e2858
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/RadioCapability.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.modem;
+@JavaDerive(toString=true) @VintfStability
+parcelable RadioCapability {
+  int session;
+  int phase;
+  int raf;
+  String logicalModemUuid;
+  int status;
+  const int PHASE_CONFIGURED = 0;
+  const int PHASE_START = 1;
+  const int PHASE_APPLY = 2;
+  const int PHASE_UNSOL_RSP = 3;
+  const int PHASE_FINISH = 4;
+  const int STATUS_NONE = 0;
+  const int STATUS_SUCCESS = 1;
+  const int STATUS_FAIL = 2;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/RadioState.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/RadioState.aidl
new file mode 100644
index 0000000..57f2941
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/RadioState.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.modem;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum RadioState {
+  OFF = 0,
+  UNAVAILABLE = 1,
+  ON = 10,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ResetNvType.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ResetNvType.aidl
new file mode 100644
index 0000000..e3b5796
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/ResetNvType.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.modem;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum ResetNvType {
+  RELOAD = 0,
+  ERASE = 1,
+  FACTORY_RESET = 2,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/AccessTechnologySpecificInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/AccessTechnologySpecificInfo.aidl
new file mode 100644
index 0000000..28d8862
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/AccessTechnologySpecificInfo.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+union AccessTechnologySpecificInfo {
+  boolean noinit;
+  android.hardware.radio.network.Cdma2000RegistrationInfo cdmaInfo;
+  android.hardware.radio.network.EutranRegistrationInfo eutranInfo;
+  android.hardware.radio.network.NrVopsInfo ngranNrVopsInfo;
+  boolean geranDtmSupported;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/BarringInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/BarringInfo.aidl
new file mode 100644
index 0000000..e105b39
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/BarringInfo.aidl
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable BarringInfo {
+  int serviceType;
+  int barringType;
+  @nullable android.hardware.radio.network.BarringTypeSpecificInfo barringTypeSpecificInfo;
+  const int BARRING_TYPE_NONE = 0;
+  const int BARRING_TYPE_CONDITIONAL = 1;
+  const int BARRING_TYPE_UNCONDITIONAL = 2;
+  const int SERVICE_TYPE_CS_SERVICE = 0;
+  const int SERVICE_TYPE_PS_SERVICE = 1;
+  const int SERVICE_TYPE_CS_VOICE = 2;
+  const int SERVICE_TYPE_MO_SIGNALLING = 3;
+  const int SERVICE_TYPE_MO_DATA = 4;
+  const int SERVICE_TYPE_CS_FALLBACK = 5;
+  const int SERVICE_TYPE_MMTEL_VOICE = 6;
+  const int SERVICE_TYPE_MMTEL_VIDEO = 7;
+  const int SERVICE_TYPE_EMERGENCY = 8;
+  const int SERVICE_TYPE_SMS = 9;
+  const int SERVICE_TYPE_OPERATOR_1 = 1001;
+  const int SERVICE_TYPE_OPERATOR_2 = 1002;
+  const int SERVICE_TYPE_OPERATOR_3 = 1003;
+  const int SERVICE_TYPE_OPERATOR_4 = 1004;
+  const int SERVICE_TYPE_OPERATOR_5 = 1005;
+  const int SERVICE_TYPE_OPERATOR_6 = 1006;
+  const int SERVICE_TYPE_OPERATOR_7 = 1007;
+  const int SERVICE_TYPE_OPERATOR_8 = 1008;
+  const int SERVICE_TYPE_OPERATOR_9 = 1009;
+  const int SERVICE_TYPE_OPERATOR_10 = 1010;
+  const int SERVICE_TYPE_OPERATOR_11 = 1011;
+  const int SERVICE_TYPE_OPERATOR_12 = 1012;
+  const int SERVICE_TYPE_OPERATOR_13 = 1013;
+  const int SERVICE_TYPE_OPERATOR_14 = 1014;
+  const int SERVICE_TYPE_OPERATOR_15 = 1015;
+  const int SERVICE_TYPE_OPERATOR_16 = 1016;
+  const int SERVICE_TYPE_OPERATOR_17 = 1017;
+  const int SERVICE_TYPE_OPERATOR_18 = 1018;
+  const int SERVICE_TYPE_OPERATOR_19 = 1019;
+  const int SERVICE_TYPE_OPERATOR_20 = 1020;
+  const int SERVICE_TYPE_OPERATOR_21 = 1021;
+  const int SERVICE_TYPE_OPERATOR_22 = 1022;
+  const int SERVICE_TYPE_OPERATOR_23 = 1023;
+  const int SERVICE_TYPE_OPERATOR_24 = 1024;
+  const int SERVICE_TYPE_OPERATOR_25 = 1025;
+  const int SERVICE_TYPE_OPERATOR_26 = 1026;
+  const int SERVICE_TYPE_OPERATOR_27 = 1027;
+  const int SERVICE_TYPE_OPERATOR_28 = 1028;
+  const int SERVICE_TYPE_OPERATOR_29 = 1029;
+  const int SERVICE_TYPE_OPERATOR_30 = 1030;
+  const int SERVICE_TYPE_OPERATOR_31 = 1031;
+  const int SERVICE_TYPE_OPERATOR_32 = 1032;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/BarringTypeSpecificInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/BarringTypeSpecificInfo.aidl
new file mode 100644
index 0000000..a813633
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/BarringTypeSpecificInfo.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable BarringTypeSpecificInfo {
+  int factor;
+  int timeSeconds;
+  boolean isBarred;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/Cdma2000RegistrationInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/Cdma2000RegistrationInfo.aidl
new file mode 100644
index 0000000..74c4e29
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/Cdma2000RegistrationInfo.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable Cdma2000RegistrationInfo {
+  boolean cssSupported;
+  int roamingIndicator;
+  int systemIsInPrl;
+  int defaultRoamingIndicator;
+  const int PRL_INDICATOR_NOT_REGISTERED = -1;
+  const int PRL_INDICATOR_NOT_IN_PRL = 0;
+  const int PRL_INDICATOR_IN_PRL = 1;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CdmaRoamingType.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CdmaRoamingType.aidl
new file mode 100644
index 0000000..24ec26b
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CdmaRoamingType.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum CdmaRoamingType {
+  HOME_NETWORK = 0,
+  AFFILIATED_ROAM = 1,
+  ANY_ROAM = 2,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CdmaSignalStrength.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CdmaSignalStrength.aidl
new file mode 100644
index 0000000..e2f97bf
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CdmaSignalStrength.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable CdmaSignalStrength {
+  int dbm;
+  int ecio;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellConnectionStatus.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellConnectionStatus.aidl
new file mode 100644
index 0000000..8986d71
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellConnectionStatus.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum CellConnectionStatus {
+  NONE = 0,
+  PRIMARY_SERVING = 1,
+  SECONDARY_SERVING = 2,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentity.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentity.aidl
new file mode 100644
index 0000000..2ee92de
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentity.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+union CellIdentity {
+  boolean noinit;
+  android.hardware.radio.network.CellIdentityGsm gsm;
+  android.hardware.radio.network.CellIdentityWcdma wcdma;
+  android.hardware.radio.network.CellIdentityTdscdma tdscdma;
+  android.hardware.radio.network.CellIdentityCdma cdma;
+  android.hardware.radio.network.CellIdentityLte lte;
+  android.hardware.radio.network.CellIdentityNr nr;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityCdma.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityCdma.aidl
new file mode 100644
index 0000000..d659a28
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityCdma.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable CellIdentityCdma {
+  int networkId;
+  int systemId;
+  int baseStationId;
+  int longitude;
+  int latitude;
+  android.hardware.radio.network.OperatorInfo operatorNames;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityGsm.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityGsm.aidl
new file mode 100644
index 0000000..d3193be
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityGsm.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable CellIdentityGsm {
+  String mcc;
+  String mnc;
+  int lac;
+  int cid;
+  int arfcn;
+  byte bsic;
+  android.hardware.radio.network.OperatorInfo operatorNames;
+  String[] additionalPlmns;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityLte.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityLte.aidl
new file mode 100644
index 0000000..2ae7b43
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityLte.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable CellIdentityLte {
+  String mcc;
+  String mnc;
+  int ci;
+  int pci;
+  int tac;
+  int earfcn;
+  android.hardware.radio.network.OperatorInfo operatorNames;
+  int bandwidth;
+  String[] additionalPlmns;
+  @nullable android.hardware.radio.network.ClosedSubscriberGroupInfo csgInfo;
+  android.hardware.radio.network.EutranBands[] bands;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityNr.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityNr.aidl
new file mode 100644
index 0000000..b30af50
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityNr.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable CellIdentityNr {
+  String mcc;
+  String mnc;
+  long nci;
+  int pci;
+  int tac;
+  int nrarfcn;
+  android.hardware.radio.network.OperatorInfo operatorNames;
+  String[] additionalPlmns;
+  android.hardware.radio.network.NgranBands[] bands;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityTdscdma.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityTdscdma.aidl
new file mode 100644
index 0000000..e99d147
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityTdscdma.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable CellIdentityTdscdma {
+  String mcc;
+  String mnc;
+  int lac;
+  int cid;
+  int cpid;
+  int uarfcn;
+  android.hardware.radio.network.OperatorInfo operatorNames;
+  String[] additionalPlmns;
+  @nullable android.hardware.radio.network.ClosedSubscriberGroupInfo csgInfo;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityWcdma.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityWcdma.aidl
new file mode 100644
index 0000000..12001fc
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellIdentityWcdma.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable CellIdentityWcdma {
+  String mcc;
+  String mnc;
+  int lac;
+  int cid;
+  int psc;
+  int uarfcn;
+  android.hardware.radio.network.OperatorInfo operatorNames;
+  String[] additionalPlmns;
+  @nullable android.hardware.radio.network.ClosedSubscriberGroupInfo csgInfo;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfo.aidl
new file mode 100644
index 0000000..467c6b7
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfo.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable CellInfo {
+  boolean registered;
+  android.hardware.radio.network.CellConnectionStatus connectionStatus;
+  android.hardware.radio.network.CellInfoRatSpecificInfo ratSpecificInfo;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoCdma.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoCdma.aidl
new file mode 100644
index 0000000..e3bf46b
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoCdma.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable CellInfoCdma {
+  android.hardware.radio.network.CellIdentityCdma cellIdentityCdma;
+  android.hardware.radio.network.CdmaSignalStrength signalStrengthCdma;
+  android.hardware.radio.network.EvdoSignalStrength signalStrengthEvdo;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoGsm.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoGsm.aidl
new file mode 100644
index 0000000..84dcd07
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoGsm.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable CellInfoGsm {
+  android.hardware.radio.network.CellIdentityGsm cellIdentityGsm;
+  android.hardware.radio.network.GsmSignalStrength signalStrengthGsm;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoLte.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoLte.aidl
new file mode 100644
index 0000000..221340b
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoLte.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable CellInfoLte {
+  android.hardware.radio.network.CellIdentityLte cellIdentityLte;
+  android.hardware.radio.network.LteSignalStrength signalStrengthLte;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoNr.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoNr.aidl
new file mode 100644
index 0000000..b392c1d
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoNr.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable CellInfoNr {
+  android.hardware.radio.network.CellIdentityNr cellIdentityNr;
+  android.hardware.radio.network.NrSignalStrength signalStrengthNr;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoRatSpecificInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoRatSpecificInfo.aidl
new file mode 100644
index 0000000..4ab0640
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoRatSpecificInfo.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+union CellInfoRatSpecificInfo {
+  android.hardware.radio.network.CellInfoGsm gsm;
+  android.hardware.radio.network.CellInfoWcdma wcdma;
+  android.hardware.radio.network.CellInfoTdscdma tdscdma;
+  android.hardware.radio.network.CellInfoLte lte;
+  android.hardware.radio.network.CellInfoNr nr;
+  android.hardware.radio.network.CellInfoCdma cdma;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoTdscdma.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoTdscdma.aidl
new file mode 100644
index 0000000..138b35c
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoTdscdma.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable CellInfoTdscdma {
+  android.hardware.radio.network.CellIdentityTdscdma cellIdentityTdscdma;
+  android.hardware.radio.network.TdscdmaSignalStrength signalStrengthTdscdma;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoWcdma.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoWcdma.aidl
new file mode 100644
index 0000000..cf7b135
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/CellInfoWcdma.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable CellInfoWcdma {
+  android.hardware.radio.network.CellIdentityWcdma cellIdentityWcdma;
+  android.hardware.radio.network.WcdmaSignalStrength signalStrengthWcdma;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/ClosedSubscriberGroupInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/ClosedSubscriberGroupInfo.aidl
new file mode 100644
index 0000000..fe734c8
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/ClosedSubscriberGroupInfo.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable ClosedSubscriberGroupInfo {
+  boolean csgIndication;
+  String homeNodebName;
+  int csgIdentity;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/Domain.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/Domain.aidl
new file mode 100644
index 0000000..209cf5e
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/Domain.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum Domain {
+  CS = 1,
+  PS = 2,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EutranBands.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EutranBands.aidl
new file mode 100644
index 0000000..57fac3f
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EutranBands.aidl
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum EutranBands {
+  BAND_1 = 1,
+  BAND_2 = 2,
+  BAND_3 = 3,
+  BAND_4 = 4,
+  BAND_5 = 5,
+  BAND_6 = 6,
+  BAND_7 = 7,
+  BAND_8 = 8,
+  BAND_9 = 9,
+  BAND_10 = 10,
+  BAND_11 = 11,
+  BAND_12 = 12,
+  BAND_13 = 13,
+  BAND_14 = 14,
+  BAND_17 = 17,
+  BAND_18 = 18,
+  BAND_19 = 19,
+  BAND_20 = 20,
+  BAND_21 = 21,
+  BAND_22 = 22,
+  BAND_23 = 23,
+  BAND_24 = 24,
+  BAND_25 = 25,
+  BAND_26 = 26,
+  BAND_27 = 27,
+  BAND_28 = 28,
+  BAND_30 = 30,
+  BAND_31 = 31,
+  BAND_33 = 33,
+  BAND_34 = 34,
+  BAND_35 = 35,
+  BAND_36 = 36,
+  BAND_37 = 37,
+  BAND_38 = 38,
+  BAND_39 = 39,
+  BAND_40 = 40,
+  BAND_41 = 41,
+  BAND_42 = 42,
+  BAND_43 = 43,
+  BAND_44 = 44,
+  BAND_45 = 45,
+  BAND_46 = 46,
+  BAND_47 = 47,
+  BAND_48 = 48,
+  BAND_65 = 65,
+  BAND_66 = 66,
+  BAND_68 = 68,
+  BAND_70 = 70,
+  BAND_49 = 49,
+  BAND_50 = 50,
+  BAND_51 = 51,
+  BAND_52 = 52,
+  BAND_53 = 53,
+  BAND_71 = 71,
+  BAND_72 = 72,
+  BAND_73 = 73,
+  BAND_74 = 74,
+  BAND_85 = 85,
+  BAND_87 = 87,
+  BAND_88 = 88,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EutranRegistrationInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EutranRegistrationInfo.aidl
new file mode 100644
index 0000000..dfbf881
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EutranRegistrationInfo.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable EutranRegistrationInfo {
+  android.hardware.radio.network.LteVopsInfo lteVopsInfo;
+  android.hardware.radio.network.NrIndicators nrIndicators;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EvdoSignalStrength.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EvdoSignalStrength.aidl
new file mode 100644
index 0000000..7c56711
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EvdoSignalStrength.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable EvdoSignalStrength {
+  int dbm;
+  int ecio;
+  int signalNoiseRatio;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/GeranBands.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/GeranBands.aidl
new file mode 100644
index 0000000..135935f
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/GeranBands.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum GeranBands {
+  BAND_T380 = 1,
+  BAND_T410 = 2,
+  BAND_450 = 3,
+  BAND_480 = 4,
+  BAND_710 = 5,
+  BAND_750 = 6,
+  BAND_T810 = 7,
+  BAND_850 = 8,
+  BAND_P900 = 9,
+  BAND_E900 = 10,
+  BAND_R900 = 11,
+  BAND_DCS1800 = 12,
+  BAND_PCS1900 = 13,
+  BAND_ER900 = 14,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/GsmSignalStrength.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/GsmSignalStrength.aidl
new file mode 100644
index 0000000..2b53b39
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/GsmSignalStrength.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable GsmSignalStrength {
+  int signalStrength;
+  int bitErrorRate;
+  int timingAdvance;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl
new file mode 100644
index 0000000..2b70e45
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@VintfStability
+interface IRadioNetwork {
+  oneway void getAllowedNetworkTypesBitmap(in int serial);
+  oneway void getAvailableBandModes(in int serial);
+  oneway void getAvailableNetworks(in int serial);
+  oneway void getBarringInfo(in int serial);
+  oneway void getCdmaRoamingPreference(in int serial);
+  oneway void getCellInfoList(in int serial);
+  oneway void getDataRegistrationState(in int serial);
+  oneway void getImsRegistrationState(in int serial);
+  oneway void getNetworkSelectionMode(in int serial);
+  oneway void getOperator(in int serial);
+  oneway void getSignalStrength(in int serial);
+  oneway void getSystemSelectionChannels(in int serial);
+  oneway void getVoiceRadioTechnology(in int serial);
+  oneway void getVoiceRegistrationState(in int serial);
+  oneway void isNrDualConnectivityEnabled(in int serial);
+  oneway void responseAcknowledgement();
+  oneway void setAllowedNetworkTypesBitmap(in int serial, in int networkTypeBitmap);
+  oneway void setBandMode(in int serial, in android.hardware.radio.network.RadioBandMode mode);
+  oneway void setBarringPassword(in int serial, in String facility, in String oldPassword, in String newPassword);
+  oneway void setCdmaRoamingPreference(in int serial, in android.hardware.radio.network.CdmaRoamingType type);
+  oneway void setCellInfoListRate(in int serial, in int rate);
+  oneway void setIndicationFilter(in int serial, in int indicationFilter);
+  oneway void setLinkCapacityReportingCriteria(in int serial, in int hysteresisMs, in int hysteresisDlKbps, in int hysteresisUlKbps, in int[] thresholdsDownlinkKbps, in int[] thresholdsUplinkKbps, in android.hardware.radio.AccessNetwork accessNetwork);
+  oneway void setLocationUpdates(in int serial, in boolean enable);
+  oneway void setNetworkSelectionModeAutomatic(in int serial);
+  oneway void setNetworkSelectionModeManual(in int serial, in String operatorNumeric, in android.hardware.radio.AccessNetwork ran);
+  oneway void setNrDualConnectivityState(in int serial, in android.hardware.radio.network.NrDualConnectivityState nrDualConnectivityState);
+  oneway void setResponseFunctions(in android.hardware.radio.network.IRadioNetworkResponse radioNetworkResponse, in android.hardware.radio.network.IRadioNetworkIndication radioNetworkIndication);
+  oneway void setSignalStrengthReportingCriteria(in int serial, in android.hardware.radio.network.SignalThresholdInfo[] signalThresholdInfos);
+  oneway void setSuppServiceNotifications(in int serial, in boolean enable);
+  oneway void setSystemSelectionChannels(in int serial, in boolean specifyChannels, in android.hardware.radio.network.RadioAccessSpecifier[] specifiers);
+  oneway void startNetworkScan(in int serial, in android.hardware.radio.network.NetworkScanRequest request);
+  oneway void stopNetworkScan(in int serial);
+  oneway void supplyNetworkDepersonalization(in int serial, in String netPin);
+  oneway void setUsageSetting(in int serial, in android.hardware.radio.network.UsageSetting usageSetting);
+  oneway void getUsageSetting(in int serial);
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkIndication.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkIndication.aidl
new file mode 100644
index 0000000..bd03c51
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkIndication.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@VintfStability
+interface IRadioNetworkIndication {
+  oneway void barringInfoChanged(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.network.CellIdentity cellIdentity, in android.hardware.radio.network.BarringInfo[] barringInfos);
+  oneway void cdmaPrlChanged(in android.hardware.radio.RadioIndicationType type, in int version);
+  oneway void cellInfoList(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.network.CellInfo[] records);
+  oneway void currentLinkCapacityEstimate(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.network.LinkCapacityEstimate lce);
+  oneway void currentPhysicalChannelConfigs(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.network.PhysicalChannelConfig[] configs);
+  oneway void currentSignalStrength(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.network.SignalStrength signalStrength);
+  oneway void imsNetworkStateChanged(in android.hardware.radio.RadioIndicationType type);
+  oneway void networkScanResult(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.network.NetworkScanResult result);
+  oneway void networkStateChanged(in android.hardware.radio.RadioIndicationType type);
+  oneway void nitzTimeReceived(in android.hardware.radio.RadioIndicationType type, in String nitzTime, in long receivedTimeMs, in long ageMs);
+  oneway void registrationFailed(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.network.CellIdentity cellIdentity, in String chosenPlmn, in int domain, in int causeCode, in int additionalCauseCode);
+  oneway void restrictedStateChanged(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.network.PhoneRestrictedState state);
+  oneway void suppSvcNotify(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.network.SuppSvcNotification suppSvc);
+  oneway void voiceRadioTechChanged(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.RadioTechnology rat);
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl
new file mode 100644
index 0000000..5f6c736
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@VintfStability
+interface IRadioNetworkResponse {
+  oneway void acknowledgeRequest(in int serial);
+  oneway void getAllowedNetworkTypesBitmapResponse(in android.hardware.radio.RadioResponseInfo info, in int networkTypeBitmap);
+  oneway void getAvailableBandModesResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.RadioBandMode[] bandModes);
+  oneway void getAvailableNetworksResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.OperatorInfo[] networkInfos);
+  oneway void getBarringInfoResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.CellIdentity cellIdentity, in android.hardware.radio.network.BarringInfo[] barringInfos);
+  oneway void getCdmaRoamingPreferenceResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.CdmaRoamingType type);
+  oneway void getCellInfoListResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.CellInfo[] cellInfo);
+  oneway void getDataRegistrationStateResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.RegStateResult dataRegResponse);
+  oneway void getImsRegistrationStateResponse(in android.hardware.radio.RadioResponseInfo info, in boolean isRegistered, in android.hardware.radio.RadioTechnologyFamily ratFamily);
+  oneway void getNetworkSelectionModeResponse(in android.hardware.radio.RadioResponseInfo info, in boolean manual);
+  oneway void getOperatorResponse(in android.hardware.radio.RadioResponseInfo info, in String longName, in String shortName, in String numeric);
+  oneway void getSignalStrengthResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.SignalStrength signalStrength);
+  oneway void getSystemSelectionChannelsResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.RadioAccessSpecifier[] specifiers);
+  oneway void getVoiceRadioTechnologyResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.RadioTechnology rat);
+  oneway void getVoiceRegistrationStateResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.RegStateResult voiceRegResponse);
+  oneway void isNrDualConnectivityEnabledResponse(in android.hardware.radio.RadioResponseInfo info, in boolean isEnabled);
+  oneway void setAllowedNetworkTypesBitmapResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setBandModeResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setBarringPasswordResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setCdmaRoamingPreferenceResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setCellInfoListRateResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setIndicationFilterResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setLinkCapacityReportingCriteriaResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setLocationUpdatesResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setNetworkSelectionModeAutomaticResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setNetworkSelectionModeManualResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setNrDualConnectivityStateResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setSignalStrengthReportingCriteriaResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setSuppServiceNotificationsResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setSystemSelectionChannelsResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void startNetworkScanResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void stopNetworkScanResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void supplyNetworkDepersonalizationResponse(in android.hardware.radio.RadioResponseInfo info, in int remainingRetries);
+  oneway void setUsageSettingResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void getUsageSettingResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.UsageSetting usageSetting);
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IndicationFilter.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IndicationFilter.aidl
new file mode 100644
index 0000000..d9ed68e
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IndicationFilter.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum IndicationFilter {
+  NONE = 0,
+  ALL = -1,
+  SIGNAL_STRENGTH = 1,
+  FULL_NETWORK_STATE = 2,
+  DATA_CALL_DORMANCY_CHANGED = 4,
+  LINK_CAPACITY_ESTIMATE = 8,
+  PHYSICAL_CHANNEL_CONFIG = 16,
+  REGISTRATION_FAILURE = 32,
+  BARRING_INFO = 64,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/LceDataInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/LceDataInfo.aidl
new file mode 100644
index 0000000..27b16c1
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/LceDataInfo.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable LceDataInfo {
+  int lastHopCapacityKbps;
+  byte confidenceLevel;
+  boolean lceSuspended;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/LinkCapacityEstimate.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/LinkCapacityEstimate.aidl
new file mode 100644
index 0000000..5707b8e
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/LinkCapacityEstimate.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable LinkCapacityEstimate {
+  int downlinkCapacityKbps;
+  int uplinkCapacityKbps;
+  int secondaryDownlinkCapacityKbps;
+  int secondaryUplinkCapacityKbps;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/LteSignalStrength.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/LteSignalStrength.aidl
new file mode 100644
index 0000000..b5b8579
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/LteSignalStrength.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable LteSignalStrength {
+  int signalStrength;
+  int rsrp;
+  int rsrq;
+  int rssnr;
+  int cqi;
+  int timingAdvance;
+  int cqiTableIndex;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/LteVopsInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/LteVopsInfo.aidl
new file mode 100644
index 0000000..6d8dd4e
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/LteVopsInfo.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable LteVopsInfo {
+  boolean isVopsSupported;
+  boolean isEmcBearerSupported;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NetworkScanRequest.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NetworkScanRequest.aidl
new file mode 100644
index 0000000..6039740
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NetworkScanRequest.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable NetworkScanRequest {
+  int type;
+  int interval;
+  android.hardware.radio.network.RadioAccessSpecifier[] specifiers;
+  int maxSearchTime;
+  boolean incrementalResults;
+  int incrementalResultsPeriodicity;
+  String[] mccMncs;
+  const int RADIO_ACCESS_SPECIFIER_MAX_SIZE = 8;
+  const int INCREMENTAL_RESULTS_PREIODICITY_RANGE_MIN = 1;
+  const int INCREMENTAL_RESULTS_PREIODICITY_RANGE_MAX = 10;
+  const int MAX_SEARCH_TIME_RANGE_MIN = 60;
+  const int MAX_SEARCH_TIME_RANGE_MAX = 3600;
+  const int SCAN_INTERVAL_RANGE_MIN = 5;
+  const int SCAN_INTERVAL_RANGE_MAX = 300;
+  const int SCAN_TYPE_ONE_SHOT = 0;
+  const int SCAN_TYPE_PERIODIC = 1;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NetworkScanResult.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NetworkScanResult.aidl
new file mode 100644
index 0000000..4e392d0
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NetworkScanResult.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable NetworkScanResult {
+  int status;
+  android.hardware.radio.RadioError error;
+  android.hardware.radio.network.CellInfo[] networkInfos;
+  const int SCAN_STATUS_PARTIAL = 1;
+  const int SCAN_STATUS_COMPLETE = 2;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NgranBands.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NgranBands.aidl
new file mode 100644
index 0000000..5904690
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NgranBands.aidl
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum NgranBands {
+  BAND_1 = 1,
+  BAND_2 = 2,
+  BAND_3 = 3,
+  BAND_5 = 5,
+  BAND_7 = 7,
+  BAND_8 = 8,
+  BAND_12 = 12,
+  BAND_14 = 14,
+  BAND_18 = 18,
+  BAND_20 = 20,
+  BAND_25 = 25,
+  BAND_26 = 26,
+  BAND_28 = 28,
+  BAND_29 = 29,
+  BAND_30 = 30,
+  BAND_34 = 34,
+  BAND_38 = 38,
+  BAND_39 = 39,
+  BAND_40 = 40,
+  BAND_41 = 41,
+  BAND_46 = 46,
+  BAND_48 = 48,
+  BAND_50 = 50,
+  BAND_51 = 51,
+  BAND_53 = 53,
+  BAND_65 = 65,
+  BAND_66 = 66,
+  BAND_70 = 70,
+  BAND_71 = 71,
+  BAND_74 = 74,
+  BAND_75 = 75,
+  BAND_76 = 76,
+  BAND_77 = 77,
+  BAND_78 = 78,
+  BAND_79 = 79,
+  BAND_80 = 80,
+  BAND_81 = 81,
+  BAND_82 = 82,
+  BAND_83 = 83,
+  BAND_84 = 84,
+  BAND_86 = 86,
+  BAND_89 = 89,
+  BAND_90 = 90,
+  BAND_91 = 91,
+  BAND_92 = 92,
+  BAND_93 = 93,
+  BAND_94 = 94,
+  BAND_95 = 95,
+  BAND_96 = 96,
+  BAND_257 = 257,
+  BAND_258 = 258,
+  BAND_260 = 260,
+  BAND_261 = 261,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrDualConnectivityState.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrDualConnectivityState.aidl
new file mode 100644
index 0000000..62c2a56
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrDualConnectivityState.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@Backing(type="byte") @JavaDerive(toString=true) @VintfStability
+enum NrDualConnectivityState {
+  ENABLE = 1,
+  DISABLE = 2,
+  DISABLE_IMMEDIATE = 3,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrIndicators.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrIndicators.aidl
new file mode 100644
index 0000000..88429f6
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrIndicators.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable NrIndicators {
+  boolean isEndcAvailable;
+  boolean isDcNrRestricted;
+  boolean isNrAvailable;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrSignalStrength.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrSignalStrength.aidl
new file mode 100644
index 0000000..98bbe6b
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrSignalStrength.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable NrSignalStrength {
+  int ssRsrp;
+  int ssRsrq;
+  int ssSinr;
+  int csiRsrp;
+  int csiRsrq;
+  int csiSinr;
+  int csiCqiTableIndex;
+  byte[] csiCqiReport;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrVopsInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrVopsInfo.aidl
new file mode 100644
index 0000000..e5a0a70
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/NrVopsInfo.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable NrVopsInfo {
+  byte vopsSupported;
+  byte emcSupported;
+  byte emfSupported;
+  const byte EMC_INDICATOR_NOT_SUPPORTED = 0;
+  const byte EMC_INDICATOR_NR_CONNECTED_TO_5GCN = 1;
+  const byte EMC_INDICATOR_EUTRA_CONNECTED_TO_5GCN = 2;
+  const byte EMC_INDICATOR_BOTH_NR_EUTRA_CONNECTED_TO_5GCN = 3;
+  const byte EMF_INDICATOR_NOT_SUPPORTED = 0;
+  const byte EMF_INDICATOR_NR_CONNECTED_TO_5GCN = 1;
+  const byte EMF_INDICATOR_EUTRA_CONNECTED_TO_5GCN = 2;
+  const byte EMF_INDICATOR_BOTH_NR_EUTRA_CONNECTED_TO_5GCN = 3;
+  const byte VOPS_INDICATOR_VOPS_NOT_SUPPORTED = 0;
+  const byte VOPS_INDICATOR_VOPS_OVER_3GPP = 1;
+  const byte VOPS_INDICATOR_VOPS_OVER_NON_3GPP = 2;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/OperatorInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/OperatorInfo.aidl
new file mode 100644
index 0000000..034150e
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/OperatorInfo.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable OperatorInfo {
+  String alphaLong;
+  String alphaShort;
+  String operatorNumeric;
+  int status;
+  const int STATUS_UNKNOWN = 0;
+  const int STATUS_AVAILABLE = 1;
+  const int STATUS_CURRENT = 2;
+  const int STATUS_FORBIDDEN = 3;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/PhoneRestrictedState.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/PhoneRestrictedState.aidl
new file mode 100644
index 0000000..41555f9
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/PhoneRestrictedState.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum PhoneRestrictedState {
+  NONE = 0,
+  CS_EMERGENCY = 1,
+  CS_NORMAL = 2,
+  CS_ALL = 4,
+  PS_ALL = 16,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/PhysicalChannelConfig.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/PhysicalChannelConfig.aidl
new file mode 100644
index 0000000..928c6b7
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/PhysicalChannelConfig.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable PhysicalChannelConfig {
+  android.hardware.radio.network.CellConnectionStatus status;
+  android.hardware.radio.RadioTechnology rat;
+  int downlinkChannelNumber;
+  int uplinkChannelNumber;
+  int cellBandwidthDownlinkKhz;
+  int cellBandwidthUplinkKhz;
+  int[] contextIds;
+  int physicalCellId;
+  android.hardware.radio.network.PhysicalChannelConfigBand band;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/PhysicalChannelConfigBand.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/PhysicalChannelConfigBand.aidl
new file mode 100644
index 0000000..efc64a6
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/PhysicalChannelConfigBand.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+union PhysicalChannelConfigBand {
+  boolean noinit;
+  android.hardware.radio.network.GeranBands geranBand;
+  android.hardware.radio.network.UtranBands utranBand;
+  android.hardware.radio.network.EutranBands eutranBand;
+  android.hardware.radio.network.NgranBands ngranBand;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RadioAccessSpecifier.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RadioAccessSpecifier.aidl
new file mode 100644
index 0000000..1566bb5
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RadioAccessSpecifier.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable RadioAccessSpecifier {
+  android.hardware.radio.AccessNetwork accessNetwork;
+  android.hardware.radio.network.RadioAccessSpecifierBands bands;
+  int[] channels;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RadioAccessSpecifierBands.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RadioAccessSpecifierBands.aidl
new file mode 100644
index 0000000..a6ac12a
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RadioAccessSpecifierBands.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+union RadioAccessSpecifierBands {
+  boolean noinit;
+  android.hardware.radio.network.GeranBands[] geranBands;
+  android.hardware.radio.network.UtranBands[] utranBands;
+  android.hardware.radio.network.EutranBands[] eutranBands;
+  android.hardware.radio.network.NgranBands[] ngranBands;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RadioBandMode.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RadioBandMode.aidl
new file mode 100644
index 0000000..e9a9f60
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RadioBandMode.aidl
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum RadioBandMode {
+  BAND_MODE_UNSPECIFIED = 0,
+  BAND_MODE_EURO = 1,
+  BAND_MODE_USA = 2,
+  BAND_MODE_JPN = 3,
+  BAND_MODE_AUS = 4,
+  BAND_MODE_AUS_2 = 5,
+  BAND_MODE_CELL_800 = 6,
+  BAND_MODE_PCS = 7,
+  BAND_MODE_JTACS = 8,
+  BAND_MODE_KOREA_PCS = 9,
+  BAND_MODE_5_450M = 10,
+  BAND_MODE_IMT2000 = 11,
+  BAND_MODE_7_700M_2 = 12,
+  BAND_MODE_8_1800M = 13,
+  BAND_MODE_9_900M = 14,
+  BAND_MODE_10_800M_2 = 15,
+  BAND_MODE_EURO_PAMR_400M = 16,
+  BAND_MODE_AWS = 17,
+  BAND_MODE_USA_2500M = 18,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegState.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegState.aidl
new file mode 100644
index 0000000..e6e7999
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegState.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum RegState {
+  NOT_REG_MT_NOT_SEARCHING_OP = 0,
+  REG_HOME = 1,
+  NOT_REG_MT_SEARCHING_OP = 2,
+  REG_DENIED = 3,
+  UNKNOWN = 4,
+  REG_ROAMING = 5,
+  NOT_REG_MT_NOT_SEARCHING_OP_EM = 10,
+  NOT_REG_MT_SEARCHING_OP_EM = 12,
+  REG_DENIED_EM = 13,
+  UNKNOWN_EM = 14,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegStateResult.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegStateResult.aidl
new file mode 100644
index 0000000..f0a03ae
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegStateResult.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable RegStateResult {
+  android.hardware.radio.network.RegState regState;
+  android.hardware.radio.RadioTechnology rat;
+  android.hardware.radio.network.RegistrationFailCause reasonForDenial;
+  android.hardware.radio.network.CellIdentity cellIdentity;
+  String registeredPlmn;
+  android.hardware.radio.network.AccessTechnologySpecificInfo accessTechnologySpecificInfo;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegistrationFailCause.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegistrationFailCause.aidl
new file mode 100644
index 0000000..e2cd44c
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegistrationFailCause.aidl
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum RegistrationFailCause {
+  NONE = 0,
+  IMSI_UNKNOWN_IN_HLR = 2,
+  ILLEGAL_MS = 3,
+  IMSI_UNKNOWN_IN_VLR = 4,
+  IMEI_NOT_ACCEPTED = 5,
+  ILLEGAL_ME = 6,
+  GPRS_SERVICES_NOT_ALLOWED = 7,
+  GPRS_AND_NON_GPRS_SERVICES_NOT_ALLOWED = 8,
+  MS_IDENTITY_CANNOT_BE_DERIVED_BY_NETWORK = 9,
+  IMPLICITLY_DETACHED = 10,
+  PLMN_NOT_ALLOWED = 11,
+  LOCATION_AREA_NOT_ALLOWED = 12,
+  ROAMING_NOT_ALLOWED = 13,
+  GPRS_SERVICES_NOT_ALLOWED_IN_PLMN = 14,
+  NO_SUITABLE_CELLS = 15,
+  MSC_TEMPORARILY_NOT_REACHABLE = 15,
+  NETWORK_FAILURE = 17,
+  MAC_FAILURE = 20,
+  SYNC_FAILURE = 21,
+  CONGESTION = 22,
+  GSM_AUTHENTICATION_UNACCEPTABLE = 23,
+  NOT_AUTHORIZED_FOR_THIS_CSG = 25,
+  SMS_PROVIDED_BY_GPRS_IN_ROUTING_AREA = 26,
+  SERVICE_OPTION_NOT_SUPPORTED = 32,
+  SERVICE_OPTION_NOT_SUBSCRIBED = 33,
+  SERVICE_OPTION_TEMPORARILY_OUT_OF_ORDER = 34,
+  CALL_CANNOT_BE_IDENTIFIED = 38,
+  NO_PDP_CONTEXT_ACTIVATED = 40,
+  RETRY_UPON_ENTRY_INTO_NEW_CELL_1 = 48,
+  RETRY_UPON_ENTRY_INTO_NEW_CELL_2 = 49,
+  RETRY_UPON_ENTRY_INTO_NEW_CELL_3 = 50,
+  RETRY_UPON_ENTRY_INTO_NEW_CELL_4 = 51,
+  RETRY_UPON_ENTRY_INTO_NEW_CELL_5 = 52,
+  RETRY_UPON_ENTRY_INTO_NEW_CELL_6 = 53,
+  RETRY_UPON_ENTRY_INTO_NEW_CELL_7 = 54,
+  RETRY_UPON_ENTRY_INTO_NEW_CELL_8 = 55,
+  RETRY_UPON_ENTRY_INTO_NEW_CELL_9 = 56,
+  RETRY_UPON_ENTRY_INTO_NEW_CELL_10 = 57,
+  RETRY_UPON_ENTRY_INTO_NEW_CELL_11 = 58,
+  RETRY_UPON_ENTRY_INTO_NEW_CELL_12 = 59,
+  RETRY_UPON_ENTRY_INTO_NEW_CELL_13 = 60,
+  RETRY_UPON_ENTRY_INTO_NEW_CELL_14 = 61,
+  RETRY_UPON_ENTRY_INTO_NEW_CELL_15 = 62,
+  RETRY_UPON_ENTRY_INTO_NEW_CELL_16 = 63,
+  SEMANTICALLY_INCORRECT_MESSAGE = 95,
+  INVALID_MANDATORY_INFORMATION = 96,
+  MESSAGE_TYPE_NON_EXISTENT_OR_NOT_IMPLEMENTED = 97,
+  MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 98,
+  INFORMATION_ELEMENT_NON_EXISTENT_OR_NOT_IMPLEMENTED = 99,
+  CONDITIONAL_IE_ERROR = 100,
+  MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 101,
+  PROTOCOL_ERROR_UNSPECIFIED = 111,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SignalStrength.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SignalStrength.aidl
new file mode 100644
index 0000000..1c50190
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SignalStrength.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable SignalStrength {
+  android.hardware.radio.network.GsmSignalStrength gsm;
+  android.hardware.radio.network.CdmaSignalStrength cdma;
+  android.hardware.radio.network.EvdoSignalStrength evdo;
+  android.hardware.radio.network.LteSignalStrength lte;
+  android.hardware.radio.network.TdscdmaSignalStrength tdscdma;
+  android.hardware.radio.network.WcdmaSignalStrength wcdma;
+  android.hardware.radio.network.NrSignalStrength nr;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SignalThresholdInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SignalThresholdInfo.aidl
new file mode 100644
index 0000000..040932c
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SignalThresholdInfo.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable SignalThresholdInfo {
+  int signalMeasurement;
+  int hysteresisMs;
+  int hysteresisDb;
+  int[] thresholds;
+  boolean isEnabled;
+  android.hardware.radio.AccessNetwork ran;
+  const int SIGNAL_MEASUREMENT_TYPE_RSSI = 1;
+  const int SIGNAL_MEASUREMENT_TYPE_RSCP = 2;
+  const int SIGNAL_MEASUREMENT_TYPE_RSRP = 3;
+  const int SIGNAL_MEASUREMENT_TYPE_RSRQ = 4;
+  const int SIGNAL_MEASUREMENT_TYPE_RSSNR = 5;
+  const int SIGNAL_MEASUREMENT_TYPE_SSRSRP = 6;
+  const int SIGNAL_MEASUREMENT_TYPE_SSRSRQ = 7;
+  const int SIGNAL_MEASUREMENT_TYPE_SSSINR = 8;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SuppSvcNotification.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SuppSvcNotification.aidl
new file mode 100644
index 0000000..b62c71b
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/SuppSvcNotification.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable SuppSvcNotification {
+  boolean isMT;
+  int code;
+  int index;
+  int type;
+  String number;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/TdscdmaSignalStrength.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/TdscdmaSignalStrength.aidl
new file mode 100644
index 0000000..d74c950
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/TdscdmaSignalStrength.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable TdscdmaSignalStrength {
+  int signalStrength;
+  int bitErrorRate;
+  int rscp;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/UsageSetting.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/UsageSetting.aidl
new file mode 100644
index 0000000..3ca16b5
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/UsageSetting.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum UsageSetting {
+  VOICE_CENTRIC = 1,
+  DATA_CENTRIC = 2,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/UtranBands.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/UtranBands.aidl
new file mode 100644
index 0000000..8be3da2
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/UtranBands.aidl
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum UtranBands {
+  BAND_1 = 1,
+  BAND_2 = 2,
+  BAND_3 = 3,
+  BAND_4 = 4,
+  BAND_5 = 5,
+  BAND_6 = 6,
+  BAND_7 = 7,
+  BAND_8 = 8,
+  BAND_9 = 9,
+  BAND_10 = 10,
+  BAND_11 = 11,
+  BAND_12 = 12,
+  BAND_13 = 13,
+  BAND_14 = 14,
+  BAND_19 = 19,
+  BAND_20 = 20,
+  BAND_21 = 21,
+  BAND_22 = 22,
+  BAND_25 = 25,
+  BAND_26 = 26,
+  BAND_A = 101,
+  BAND_B = 102,
+  BAND_C = 103,
+  BAND_D = 104,
+  BAND_E = 105,
+  BAND_F = 106,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/WcdmaSignalStrength.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/WcdmaSignalStrength.aidl
new file mode 100644
index 0000000..9112527
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/WcdmaSignalStrength.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.network;
+@JavaDerive(toString=true) @VintfStability
+parcelable WcdmaSignalStrength {
+  int signalStrength;
+  int bitErrorRate;
+  int rscp;
+  int ecno;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/AppStatus.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/AppStatus.aidl
new file mode 100644
index 0000000..8a41fb9
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/AppStatus.aidl
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.sim;
+@JavaDerive(toString=true) @VintfStability
+parcelable AppStatus {
+  int appType;
+  int appState;
+  android.hardware.radio.sim.PersoSubstate persoSubstate;
+  String aidPtr;
+  String appLabelPtr;
+  boolean pin1Replaced;
+  android.hardware.radio.sim.PinState pin1;
+  android.hardware.radio.sim.PinState pin2;
+  const int APP_STATE_UNKNOWN = 0;
+  const int APP_STATE_DETECTED = 1;
+  const int APP_STATE_PIN = 2;
+  const int APP_STATE_PUK = 3;
+  const int APP_STATE_SUBSCRIPTION_PERSO = 4;
+  const int APP_STATE_READY = 5;
+  const int APP_TYPE_UNKNOWN = 0;
+  const int APP_TYPE_SIM = 1;
+  const int APP_TYPE_USIM = 2;
+  const int APP_TYPE_RUIM = 3;
+  const int APP_TYPE_CSIM = 4;
+  const int APP_TYPE_ISIM = 5;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CardPowerState.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CardPowerState.aidl
new file mode 100644
index 0000000..05bc13a
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CardPowerState.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.sim;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum CardPowerState {
+  POWER_DOWN = 0,
+  POWER_UP = 1,
+  POWER_UP_PASS_THROUGH = 2,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CardStatus.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CardStatus.aidl
new file mode 100644
index 0000000..9000d43
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CardStatus.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.sim;
+@JavaDerive(toString=true) @VintfStability
+parcelable CardStatus {
+  int cardState;
+  android.hardware.radio.sim.PinState universalPinState;
+  int gsmUmtsSubscriptionAppIndex;
+  int cdmaSubscriptionAppIndex;
+  int imsSubscriptionAppIndex;
+  android.hardware.radio.sim.AppStatus[] applications;
+  String atr;
+  String iccid;
+  String eid;
+  android.hardware.radio.config.SlotPortMapping slotMap;
+  const int STATE_ABSENT = 0;
+  const int STATE_PRESENT = 1;
+  const int STATE_ERROR = 2;
+  const int STATE_RESTRICTED = 3;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/Carrier.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/Carrier.aidl
new file mode 100644
index 0000000..cc56888
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/Carrier.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.sim;
+@JavaDerive(toString=true) @VintfStability
+parcelable Carrier {
+  String mcc;
+  String mnc;
+  int matchType;
+  String matchData;
+  const int MATCH_TYPE_ALL = 0;
+  const int MATCH_TYPE_SPN = 1;
+  const int MATCH_TYPE_IMSI_PREFIX = 2;
+  const int MATCH_TYPE_GID1 = 3;
+  const int MATCH_TYPE_GID2 = 4;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CarrierRestrictions.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CarrierRestrictions.aidl
new file mode 100644
index 0000000..944f1ca
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CarrierRestrictions.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.sim;
+@JavaDerive(toString=true) @VintfStability
+parcelable CarrierRestrictions {
+  android.hardware.radio.sim.Carrier[] allowedCarriers;
+  android.hardware.radio.sim.Carrier[] excludedCarriers;
+  boolean allowedCarriersPrioritized;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CdmaSubscriptionSource.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CdmaSubscriptionSource.aidl
new file mode 100644
index 0000000..13469f3
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/CdmaSubscriptionSource.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.sim;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum CdmaSubscriptionSource {
+  RUIM_SIM = 0,
+  NV = 1,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSim.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSim.aidl
new file mode 100644
index 0000000..85a0c71
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSim.aidl
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.sim;
+@VintfStability
+interface IRadioSim {
+  oneway void areUiccApplicationsEnabled(in int serial);
+  oneway void changeIccPin2ForApp(in int serial, in String oldPin2, in String newPin2, in String aid);
+  oneway void changeIccPinForApp(in int serial, in String oldPin, in String newPin, in String aid);
+  oneway void enableUiccApplications(in int serial, in boolean enable);
+  oneway void getAllowedCarriers(in int serial);
+  oneway void getCdmaSubscription(in int serial);
+  oneway void getCdmaSubscriptionSource(in int serial);
+  oneway void getFacilityLockForApp(in int serial, in String facility, in String password, in int serviceClass, in String appId);
+  oneway void getIccCardStatus(in int serial);
+  oneway void getImsiForApp(in int serial, in String aid);
+  oneway void getSimPhonebookCapacity(in int serial);
+  oneway void getSimPhonebookRecords(in int serial);
+  oneway void iccCloseLogicalChannel(in int serial, in int channelId);
+  oneway void iccIoForApp(in int serial, in android.hardware.radio.sim.IccIo iccIo);
+  oneway void iccOpenLogicalChannel(in int serial, in String aid, in int p2);
+  oneway void iccTransmitApduBasicChannel(in int serial, in android.hardware.radio.sim.SimApdu message);
+  oneway void iccTransmitApduLogicalChannel(in int serial, in android.hardware.radio.sim.SimApdu message);
+  oneway void reportStkServiceIsRunning(in int serial);
+  oneway void requestIccSimAuthentication(in int serial, in int authContext, in String authData, in String aid);
+  oneway void responseAcknowledgement();
+  oneway void sendEnvelope(in int serial, in String contents);
+  oneway void sendEnvelopeWithStatus(in int serial, in String contents);
+  oneway void sendTerminalResponseToSim(in int serial, in String contents);
+  oneway void setAllowedCarriers(in int serial, in android.hardware.radio.sim.CarrierRestrictions carriers, in android.hardware.radio.sim.SimLockMultiSimPolicy multiSimPolicy);
+  oneway void setCarrierInfoForImsiEncryption(in int serial, in android.hardware.radio.sim.ImsiEncryptionInfo imsiEncryptionInfo);
+  oneway void setCdmaSubscriptionSource(in int serial, in android.hardware.radio.sim.CdmaSubscriptionSource cdmaSub);
+  oneway void setFacilityLockForApp(in int serial, in String facility, in boolean lockState, in String password, in int serviceClass, in String appId);
+  oneway void setResponseFunctions(in android.hardware.radio.sim.IRadioSimResponse radioSimResponse, in android.hardware.radio.sim.IRadioSimIndication radioSimIndication);
+  oneway void setSimCardPower(in int serial, in android.hardware.radio.sim.CardPowerState powerUp);
+  oneway void setUiccSubscription(in int serial, in android.hardware.radio.sim.SelectUiccSub uiccSub);
+  oneway void supplyIccPin2ForApp(in int serial, in String pin2, in String aid);
+  oneway void supplyIccPinForApp(in int serial, in String pin, in String aid);
+  oneway void supplyIccPuk2ForApp(in int serial, in String puk2, in String pin2, in String aid);
+  oneway void supplyIccPukForApp(in int serial, in String puk, in String pin, in String aid);
+  oneway void supplySimDepersonalization(in int serial, in android.hardware.radio.sim.PersoSubstate persoType, in String controlKey);
+  oneway void updateSimPhonebookRecords(in int serial, in android.hardware.radio.sim.PhonebookRecordInfo recordInfo);
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSimIndication.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSimIndication.aidl
new file mode 100644
index 0000000..d4371b8
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSimIndication.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.sim;
+@VintfStability
+interface IRadioSimIndication {
+  oneway void carrierInfoForImsiEncryption(in android.hardware.radio.RadioIndicationType info);
+  oneway void cdmaSubscriptionSourceChanged(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.sim.CdmaSubscriptionSource cdmaSource);
+  oneway void simPhonebookChanged(in android.hardware.radio.RadioIndicationType type);
+  oneway void simPhonebookRecordsReceived(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.sim.PbReceivedStatus status, in android.hardware.radio.sim.PhonebookRecordInfo[] records);
+  oneway void simRefresh(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.sim.SimRefreshResult refreshResult);
+  oneway void simStatusChanged(in android.hardware.radio.RadioIndicationType type);
+  oneway void stkEventNotify(in android.hardware.radio.RadioIndicationType type, in String cmd);
+  oneway void stkProactiveCommand(in android.hardware.radio.RadioIndicationType type, in String cmd);
+  oneway void stkSessionEnd(in android.hardware.radio.RadioIndicationType type);
+  oneway void subscriptionStatusChanged(in android.hardware.radio.RadioIndicationType type, in boolean activate);
+  oneway void uiccApplicationsEnablementChanged(in android.hardware.radio.RadioIndicationType type, in boolean enabled);
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSimResponse.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSimResponse.aidl
new file mode 100644
index 0000000..8e68e30
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IRadioSimResponse.aidl
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.sim;
+@VintfStability
+interface IRadioSimResponse {
+  oneway void acknowledgeRequest(in int serial);
+  oneway void areUiccApplicationsEnabledResponse(in android.hardware.radio.RadioResponseInfo info, in boolean enabled);
+  oneway void changeIccPin2ForAppResponse(in android.hardware.radio.RadioResponseInfo info, in int remainingRetries);
+  oneway void changeIccPinForAppResponse(in android.hardware.radio.RadioResponseInfo info, in int remainingRetries);
+  oneway void enableUiccApplicationsResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void getAllowedCarriersResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.sim.CarrierRestrictions carriers, in android.hardware.radio.sim.SimLockMultiSimPolicy multiSimPolicy);
+  oneway void getCdmaSubscriptionResponse(in android.hardware.radio.RadioResponseInfo info, in String mdn, in String hSid, in String hNid, in String min, in String prl);
+  oneway void getCdmaSubscriptionSourceResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.sim.CdmaSubscriptionSource source);
+  oneway void getFacilityLockForAppResponse(in android.hardware.radio.RadioResponseInfo info, in int response);
+  oneway void getIccCardStatusResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.sim.CardStatus cardStatus);
+  oneway void getImsiForAppResponse(in android.hardware.radio.RadioResponseInfo info, in String imsi);
+  oneway void getSimPhonebookCapacityResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.sim.PhonebookCapacity capacity);
+  oneway void getSimPhonebookRecordsResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void iccCloseLogicalChannelResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void iccIoForAppResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.sim.IccIoResult iccIo);
+  oneway void iccOpenLogicalChannelResponse(in android.hardware.radio.RadioResponseInfo info, in int channelId, in byte[] selectResponse);
+  oneway void iccTransmitApduBasicChannelResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.sim.IccIoResult result);
+  oneway void iccTransmitApduLogicalChannelResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.sim.IccIoResult result);
+  oneway void reportStkServiceIsRunningResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void requestIccSimAuthenticationResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.sim.IccIoResult result);
+  oneway void sendEnvelopeResponse(in android.hardware.radio.RadioResponseInfo info, in String commandResponse);
+  oneway void sendEnvelopeWithStatusResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.sim.IccIoResult iccIo);
+  oneway void sendTerminalResponseToSimResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setAllowedCarriersResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setCarrierInfoForImsiEncryptionResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setCdmaSubscriptionSourceResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setFacilityLockForAppResponse(in android.hardware.radio.RadioResponseInfo info, in int retry);
+  oneway void setSimCardPowerResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setUiccSubscriptionResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void supplyIccPin2ForAppResponse(in android.hardware.radio.RadioResponseInfo info, in int remainingRetries);
+  oneway void supplyIccPinForAppResponse(in android.hardware.radio.RadioResponseInfo info, in int remainingRetries);
+  oneway void supplyIccPuk2ForAppResponse(in android.hardware.radio.RadioResponseInfo info, in int remainingRetries);
+  oneway void supplyIccPukForAppResponse(in android.hardware.radio.RadioResponseInfo info, in int remainingRetries);
+  oneway void supplySimDepersonalizationResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.sim.PersoSubstate persoType, in int remainingRetries);
+  oneway void updateSimPhonebookRecordsResponse(in android.hardware.radio.RadioResponseInfo info, in int updatedRecordIndex);
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IccIo.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IccIo.aidl
new file mode 100644
index 0000000..5a312dc
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IccIo.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.sim;
+@JavaDerive(toString=true) @VintfStability
+parcelable IccIo {
+  int command;
+  int fileId;
+  String path;
+  int p1;
+  int p2;
+  int p3;
+  String data;
+  String pin2;
+  String aid;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IccIoResult.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IccIoResult.aidl
new file mode 100644
index 0000000..6c6bde2
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/IccIoResult.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.sim;
+@JavaDerive(toString=true) @VintfStability
+parcelable IccIoResult {
+  int sw1;
+  int sw2;
+  String simResponse;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/ImsiEncryptionInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/ImsiEncryptionInfo.aidl
new file mode 100644
index 0000000..05e71cd
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/ImsiEncryptionInfo.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.sim;
+@JavaDerive(toString=true) @VintfStability
+parcelable ImsiEncryptionInfo {
+  String mcc;
+  String mnc;
+  byte[] carrierKey;
+  String keyIdentifier;
+  long expirationTime;
+  byte keyType;
+  const byte PUBLIC_KEY_TYPE_EPDG = 1;
+  const byte PUBLIC_KEY_TYPE_WLAN = 2;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PbReceivedStatus.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PbReceivedStatus.aidl
new file mode 100644
index 0000000..5e96fc6
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PbReceivedStatus.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.sim;
+@Backing(type="byte") @JavaDerive(toString=true) @VintfStability
+enum PbReceivedStatus {
+  PB_RECEIVED_OK = 1,
+  PB_RECEIVED_ERROR = 2,
+  PB_RECEIVED_ABORT = 3,
+  PB_RECEIVED_FINAL = 4,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PersoSubstate.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PersoSubstate.aidl
new file mode 100644
index 0000000..e33769e
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PersoSubstate.aidl
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.sim;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum PersoSubstate {
+  UNKNOWN = 0,
+  IN_PROGRESS = 1,
+  READY = 2,
+  SIM_NETWORK = 3,
+  SIM_NETWORK_SUBSET = 4,
+  SIM_CORPORATE = 5,
+  SIM_SERVICE_PROVIDER = 6,
+  SIM_SIM = 7,
+  SIM_NETWORK_PUK = 8,
+  SIM_NETWORK_SUBSET_PUK = 9,
+  SIM_CORPORATE_PUK = 10,
+  SIM_SERVICE_PROVIDER_PUK = 11,
+  SIM_SIM_PUK = 12,
+  RUIM_NETWORK1 = 13,
+  RUIM_NETWORK2 = 14,
+  RUIM_HRPD = 15,
+  RUIM_CORPORATE = 16,
+  RUIM_SERVICE_PROVIDER = 17,
+  RUIM_RUIM = 18,
+  RUIM_NETWORK1_PUK = 19,
+  RUIM_NETWORK2_PUK = 20,
+  RUIM_HRPD_PUK = 21,
+  RUIM_CORPORATE_PUK = 22,
+  RUIM_SERVICE_PROVIDER_PUK = 23,
+  RUIM_RUIM_PUK = 24,
+  SIM_SPN = 25,
+  SIM_SPN_PUK = 26,
+  SIM_SP_EHPLMN = 27,
+  SIM_SP_EHPLMN_PUK = 28,
+  SIM_ICCID = 29,
+  SIM_ICCID_PUK = 30,
+  SIM_IMPI = 31,
+  SIM_IMPI_PUK = 32,
+  SIM_NS_SP = 33,
+  SIM_NS_SP_PUK = 34,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PhonebookCapacity.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PhonebookCapacity.aidl
new file mode 100644
index 0000000..7531c96
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PhonebookCapacity.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.sim;
+@JavaDerive(toString=true) @VintfStability
+parcelable PhonebookCapacity {
+  int maxAdnRecords;
+  int usedAdnRecords;
+  int maxEmailRecords;
+  int usedEmailRecords;
+  int maxAdditionalNumberRecords;
+  int usedAdditionalNumberRecords;
+  int maxNameLen;
+  int maxNumberLen;
+  int maxEmailLen;
+  int maxAdditionalNumberLen;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PhonebookRecordInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PhonebookRecordInfo.aidl
new file mode 100644
index 0000000..2e96a4b
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PhonebookRecordInfo.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.sim;
+@JavaDerive(toString=true) @VintfStability
+parcelable PhonebookRecordInfo {
+  int recordId;
+  String name;
+  String number;
+  String[] emails;
+  String[] additionalNumbers;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PinState.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PinState.aidl
new file mode 100644
index 0000000..5cdc6d1
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/PinState.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.sim;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum PinState {
+  UNKNOWN = 0,
+  ENABLED_NOT_VERIFIED = 1,
+  ENABLED_VERIFIED = 2,
+  DISABLED = 3,
+  ENABLED_BLOCKED = 4,
+  ENABLED_PERM_BLOCKED = 5,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SelectUiccSub.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SelectUiccSub.aidl
new file mode 100644
index 0000000..02121e6
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SelectUiccSub.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.sim;
+@JavaDerive(toString=true) @VintfStability
+parcelable SelectUiccSub {
+  int slot;
+  int appIndex;
+  int subType;
+  int actStatus;
+  const int SUBSCRIPTION_TYPE_1 = 0;
+  const int SUBSCRIPTION_TYPE_2 = 1;
+  const int SUBSCRIPTION_TYPE_3 = 2;
+  const int ACT_STATUS_DEACTIVATE = 0;
+  const int ACT_STATUS_ACTIVATE = 1;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimApdu.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimApdu.aidl
new file mode 100644
index 0000000..2201345
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimApdu.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.sim;
+@JavaDerive(toString=true) @VintfStability
+parcelable SimApdu {
+  int sessionId;
+  int cla;
+  int instruction;
+  int p1;
+  int p2;
+  int p3;
+  String data;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimLockMultiSimPolicy.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimLockMultiSimPolicy.aidl
new file mode 100644
index 0000000..4ded3e9
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimLockMultiSimPolicy.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.sim;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum SimLockMultiSimPolicy {
+  NO_MULTISIM_POLICY = 0,
+  ONE_VALID_SIM_MUST_BE_PRESENT = 1,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimRefreshResult.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimRefreshResult.aidl
new file mode 100644
index 0000000..69bf476
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimRefreshResult.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.sim;
+@JavaDerive(toString=true) @VintfStability
+parcelable SimRefreshResult {
+  int type;
+  int efId;
+  String aid;
+  const int TYPE_SIM_FILE_UPDATE = 0;
+  const int TYPE_SIM_INIT = 1;
+  const int TYPE_SIM_RESET = 2;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/AudioQuality.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/AudioQuality.aidl
new file mode 100644
index 0000000..15669ac
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/AudioQuality.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.voice;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum AudioQuality {
+  UNSPECIFIED = 0,
+  AMR = 1,
+  AMR_WB = 2,
+  GSM_EFR = 3,
+  GSM_FR = 4,
+  GSM_HR = 5,
+  EVRC = 6,
+  EVRC_B = 7,
+  EVRC_WB = 8,
+  EVRC_NW = 9,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/Call.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/Call.aidl
new file mode 100644
index 0000000..10d2ee7
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/Call.aidl
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.voice;
+@JavaDerive(toString=true) @VintfStability
+parcelable Call {
+  int state;
+  int index;
+  int toa;
+  boolean isMpty;
+  boolean isMT;
+  byte als;
+  boolean isVoice;
+  boolean isVoicePrivacy;
+  String number;
+  int numberPresentation;
+  String name;
+  int namePresentation;
+  android.hardware.radio.voice.UusInfo[] uusInfo;
+  android.hardware.radio.voice.AudioQuality audioQuality;
+  String forwardedNumber;
+  const int PRESENTATION_ALLOWED = 0;
+  const int PRESENTATION_RESTRICTED = 1;
+  const int PRESENTATION_UNKNOWN = 2;
+  const int PRESENTATION_PAYPHONE = 3;
+  const int STATE_ACTIVE = 0;
+  const int STATE_HOLDING = 1;
+  const int STATE_DIALING = 2;
+  const int STATE_ALERTING = 3;
+  const int STATE_INCOMING = 4;
+  const int STATE_WAITING = 5;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CallForwardInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CallForwardInfo.aidl
new file mode 100644
index 0000000..8e7aaab
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CallForwardInfo.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.voice;
+@JavaDerive(toString=true) @VintfStability
+parcelable CallForwardInfo {
+  int status;
+  int reason;
+  int serviceClass;
+  int toa;
+  String number;
+  int timeSeconds;
+  const int STATUS_DISABLE = 0;
+  const int STATUS_ENABLE = 1;
+  const int STATUS_INTERROGATE = 2;
+  const int STATUS_REGISTRATION = 3;
+  const int STATUS_ERASURE = 4;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaCallWaiting.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaCallWaiting.aidl
new file mode 100644
index 0000000..310f9a0
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaCallWaiting.aidl
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.voice;
+@JavaDerive(toString=true) @VintfStability
+parcelable CdmaCallWaiting {
+  String number;
+  int numberPresentation;
+  String name;
+  android.hardware.radio.voice.CdmaSignalInfoRecord signalInfoRecord;
+  int numberType;
+  int numberPlan;
+  const int NUMBER_PLAN_UNKNOWN = 0;
+  const int NUMBER_PLAN_ISDN = 1;
+  const int NUMBER_PLAN_DATA = 3;
+  const int NUMBER_PLAN_TELEX = 4;
+  const int NUMBER_PLAN_NATIONAL = 8;
+  const int NUMBER_PLAN_PRIVATE = 9;
+  const int NUMBER_PRESENTATION_ALLOWED = 0;
+  const int NUMBER_PRESENTATION_RESTRICTED = 1;
+  const int NUMBER_PRESENTATION_UNKNOWN = 2;
+  const int NUMBER_TYPE_UNKNOWN = 0;
+  const int NUMBER_TYPE_INTERNATIONAL = 1;
+  const int NUMBER_TYPE_NATIONAL = 2;
+  const int NUMBER_TYPE_NETWORK_SPECIFIC = 3;
+  const int NUMBER_TYPE_SUBSCRIBER = 4;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaDisplayInfoRecord.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaDisplayInfoRecord.aidl
new file mode 100644
index 0000000..b6b562c
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaDisplayInfoRecord.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.voice;
+@JavaDerive(toString=true) @VintfStability
+parcelable CdmaDisplayInfoRecord {
+  String alphaBuf;
+  const int CDMA_ALPHA_INFO_BUFFER_LENGTH = 64;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaInformationRecord.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaInformationRecord.aidl
new file mode 100644
index 0000000..24ae775
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaInformationRecord.aidl
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.voice;
+@JavaDerive(toString=true) @VintfStability
+parcelable CdmaInformationRecord {
+  int name;
+  android.hardware.radio.voice.CdmaDisplayInfoRecord[] display;
+  android.hardware.radio.voice.CdmaNumberInfoRecord[] number;
+  android.hardware.radio.voice.CdmaSignalInfoRecord[] signal;
+  android.hardware.radio.voice.CdmaRedirectingNumberInfoRecord[] redir;
+  android.hardware.radio.voice.CdmaLineControlInfoRecord[] lineCtrl;
+  android.hardware.radio.voice.CdmaT53ClirInfoRecord[] clir;
+  android.hardware.radio.voice.CdmaT53AudioControlInfoRecord[] audioCtrl;
+  const int CDMA_MAX_NUMBER_OF_INFO_RECS = 10;
+  const int NAME_DISPLAY = 0;
+  const int NAME_CALLED_PARTY_NUMBER = 1;
+  const int NAME_CALLING_PARTY_NUMBER = 2;
+  const int NAME_CONNECTED_NUMBER = 3;
+  const int NAME_SIGNAL = 4;
+  const int NAME_REDIRECTING_NUMBER = 5;
+  const int NAME_LINE_CONTROL = 6;
+  const int NAME_EXTENDED_DISPLAY = 7;
+  const int NAME_T53_CLIR = 8;
+  const int NAME_T53_RELEASE = 9;
+  const int NAME_T53_AUDIO_CONTROL = 10;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaLineControlInfoRecord.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaLineControlInfoRecord.aidl
new file mode 100644
index 0000000..e34b393
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaLineControlInfoRecord.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.voice;
+@JavaDerive(toString=true) @VintfStability
+parcelable CdmaLineControlInfoRecord {
+  byte lineCtrlPolarityIncluded;
+  byte lineCtrlToggle;
+  byte lineCtrlReverse;
+  byte lineCtrlPowerDenial;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaNumberInfoRecord.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaNumberInfoRecord.aidl
new file mode 100644
index 0000000..aeb0347
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaNumberInfoRecord.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.voice;
+@JavaDerive(toString=true) @VintfStability
+parcelable CdmaNumberInfoRecord {
+  String number;
+  byte numberType;
+  byte numberPlan;
+  byte pi;
+  byte si;
+  const int CDMA_NUMBER_INFO_BUFFER_LENGTH = 81;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaOtaProvisionStatus.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaOtaProvisionStatus.aidl
new file mode 100644
index 0000000..7877fda
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaOtaProvisionStatus.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.voice;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum CdmaOtaProvisionStatus {
+  SPL_UNLOCKED = 0,
+  SPC_RETRIES_EXCEEDED = 1,
+  A_KEY_EXCHANGED = 2,
+  SSD_UPDATED = 3,
+  NAM_DOWNLOADED = 4,
+  MDN_DOWNLOADED = 5,
+  IMSI_DOWNLOADED = 6,
+  PRL_DOWNLOADED = 7,
+  COMMITTED = 8,
+  OTAPA_STARTED = 9,
+  OTAPA_STOPPED = 10,
+  OTAPA_ABORTED = 11,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaRedirectingNumberInfoRecord.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaRedirectingNumberInfoRecord.aidl
new file mode 100644
index 0000000..b61b91b
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaRedirectingNumberInfoRecord.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.voice;
+@JavaDerive(toString=true) @VintfStability
+parcelable CdmaRedirectingNumberInfoRecord {
+  android.hardware.radio.voice.CdmaNumberInfoRecord redirectingNumber;
+  int redirectingReason;
+  const int REDIRECTING_REASON_UNKNOWN = 0;
+  const int REDIRECTING_REASON_CALL_FORWARDING_BUSY = 1;
+  const int REDIRECTING_REASON_CALL_FORWARDING_NO_REPLY = 2;
+  const int REDIRECTING_REASON_CALLED_DTE_OUT_OF_ORDER = 9;
+  const int REDIRECTING_REASON_CALL_FORWARDING_BY_THE_CALLED_DTE = 10;
+  const int REDIRECTING_REASON_CALL_FORWARDING_UNCONDITIONAL = 15;
+  const int REDIRECTING_REASON_RESERVED = 16;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaSignalInfoRecord.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaSignalInfoRecord.aidl
new file mode 100644
index 0000000..6c7b264
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaSignalInfoRecord.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.voice;
+@JavaDerive(toString=true) @VintfStability
+parcelable CdmaSignalInfoRecord {
+  boolean isPresent;
+  byte signalType;
+  byte alertPitch;
+  byte signal;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaT53AudioControlInfoRecord.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaT53AudioControlInfoRecord.aidl
new file mode 100644
index 0000000..438231c
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaT53AudioControlInfoRecord.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.voice;
+@JavaDerive(toString=true) @VintfStability
+parcelable CdmaT53AudioControlInfoRecord {
+  byte upLink;
+  byte downLink;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaT53ClirInfoRecord.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaT53ClirInfoRecord.aidl
new file mode 100644
index 0000000..1b254f5
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CdmaT53ClirInfoRecord.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.voice;
+@JavaDerive(toString=true) @VintfStability
+parcelable CdmaT53ClirInfoRecord {
+  byte cause;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CfData.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CfData.aidl
new file mode 100644
index 0000000..7e799c7
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/CfData.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.voice;
+@JavaDerive(toString=true) @VintfStability
+parcelable CfData {
+  android.hardware.radio.voice.CallForwardInfo[] cfInfo;
+  const int NUM_SERVICE_CLASSES = 7;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/ClipStatus.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/ClipStatus.aidl
new file mode 100644
index 0000000..3fbb0d8
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/ClipStatus.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.voice;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum ClipStatus {
+  CLIP_PROVISIONED = 0,
+  CLIP_UNPROVISIONED = 1,
+  UNKNOWN = 2,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/Dial.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/Dial.aidl
new file mode 100644
index 0000000..2b2e759
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/Dial.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.voice;
+@JavaDerive(toString=true) @VintfStability
+parcelable Dial {
+  String address;
+  int clir;
+  android.hardware.radio.voice.UusInfo[] uusInfo;
+  const int CLIR_DEFAULT = 0;
+  const int CLIR_INVOCATION = 1;
+  const int CLIR_SUPPRESSION = 2;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/EmergencyCallRouting.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/EmergencyCallRouting.aidl
new file mode 100644
index 0000000..07f011d
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/EmergencyCallRouting.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.voice;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum EmergencyCallRouting {
+  UNKNOWN = 0,
+  EMERGENCY = 1,
+  NORMAL = 2,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/EmergencyNumber.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/EmergencyNumber.aidl
new file mode 100644
index 0000000..98df8cd
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/EmergencyNumber.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.voice;
+@JavaDerive(toString=true) @VintfStability
+parcelable EmergencyNumber {
+  String number;
+  String mcc;
+  String mnc;
+  int categories;
+  String[] urns;
+  int sources;
+  const int SOURCE_NETWORK_SIGNALING = 1;
+  const int SOURCE_SIM = 2;
+  const int SOURCE_MODEM_CONFIG = 4;
+  const int SOURCE_DEFAULT = 8;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/EmergencyServiceCategory.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/EmergencyServiceCategory.aidl
new file mode 100644
index 0000000..042dd61
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/EmergencyServiceCategory.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.voice;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum EmergencyServiceCategory {
+  UNSPECIFIED = 0,
+  POLICE = 1,
+  AMBULANCE = 2,
+  FIRE_BRIGADE = 4,
+  MARINE_GUARD = 8,
+  MOUNTAIN_RESCUE = 16,
+  MIEC = 32,
+  AIEC = 64,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoice.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoice.aidl
new file mode 100644
index 0000000..603b1d6
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoice.aidl
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.voice;
+@VintfStability
+interface IRadioVoice {
+  oneway void acceptCall(in int serial);
+  oneway void cancelPendingUssd(in int serial);
+  oneway void conference(in int serial);
+  oneway void dial(in int serial, in android.hardware.radio.voice.Dial dialInfo);
+  oneway void emergencyDial(in int serial, in android.hardware.radio.voice.Dial dialInfo, in int categories, in String[] urns, in android.hardware.radio.voice.EmergencyCallRouting routing, in boolean hasKnownUserIntentEmergency, in boolean isTesting);
+  oneway void exitEmergencyCallbackMode(in int serial);
+  oneway void explicitCallTransfer(in int serial);
+  oneway void getCallForwardStatus(in int serial, in android.hardware.radio.voice.CallForwardInfo callInfo);
+  oneway void getCallWaiting(in int serial, in int serviceClass);
+  oneway void getClip(in int serial);
+  oneway void getClir(in int serial);
+  oneway void getCurrentCalls(in int serial);
+  oneway void getLastCallFailCause(in int serial);
+  oneway void getMute(in int serial);
+  oneway void getPreferredVoicePrivacy(in int serial);
+  oneway void getTtyMode(in int serial);
+  oneway void handleStkCallSetupRequestFromSim(in int serial, in boolean accept);
+  oneway void hangup(in int serial, in int gsmIndex);
+  oneway void hangupForegroundResumeBackground(in int serial);
+  oneway void hangupWaitingOrBackground(in int serial);
+  oneway void isVoNrEnabled(in int serial);
+  oneway void rejectCall(in int serial);
+  oneway void responseAcknowledgement();
+  oneway void sendBurstDtmf(in int serial, in String dtmf, in int on, in int off);
+  oneway void sendCdmaFeatureCode(in int serial, in String featureCode);
+  oneway void sendDtmf(in int serial, in String s);
+  oneway void sendUssd(in int serial, in String ussd);
+  oneway void separateConnection(in int serial, in int gsmIndex);
+  oneway void setCallForward(in int serial, in android.hardware.radio.voice.CallForwardInfo callInfo);
+  oneway void setCallWaiting(in int serial, in boolean enable, in int serviceClass);
+  oneway void setClir(in int serial, in int status);
+  oneway void setMute(in int serial, in boolean enable);
+  oneway void setPreferredVoicePrivacy(in int serial, in boolean enable);
+  oneway void setResponseFunctions(in android.hardware.radio.voice.IRadioVoiceResponse radioVoiceResponse, in android.hardware.radio.voice.IRadioVoiceIndication radioVoiceIndication);
+  oneway void setTtyMode(in int serial, in android.hardware.radio.voice.TtyMode mode);
+  oneway void setVoNrEnabled(in int serial, in boolean enable);
+  oneway void startDtmf(in int serial, in String s);
+  oneway void stopDtmf(in int serial);
+  oneway void switchWaitingOrHoldingAndActive(in int serial);
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoiceIndication.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoiceIndication.aidl
new file mode 100644
index 0000000..189ed43
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoiceIndication.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.voice;
+@VintfStability
+interface IRadioVoiceIndication {
+  oneway void callRing(in android.hardware.radio.RadioIndicationType type, in boolean isGsm, in android.hardware.radio.voice.CdmaSignalInfoRecord record);
+  oneway void callStateChanged(in android.hardware.radio.RadioIndicationType type);
+  oneway void cdmaCallWaiting(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.voice.CdmaCallWaiting callWaitingRecord);
+  oneway void cdmaInfoRec(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.voice.CdmaInformationRecord[] records);
+  oneway void cdmaOtaProvisionStatus(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.voice.CdmaOtaProvisionStatus status);
+  oneway void currentEmergencyNumberList(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.voice.EmergencyNumber[] emergencyNumberList);
+  oneway void enterEmergencyCallbackMode(in android.hardware.radio.RadioIndicationType type);
+  oneway void exitEmergencyCallbackMode(in android.hardware.radio.RadioIndicationType type);
+  oneway void indicateRingbackTone(in android.hardware.radio.RadioIndicationType type, in boolean start);
+  oneway void onSupplementaryServiceIndication(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.voice.StkCcUnsolSsResult ss);
+  oneway void onUssd(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.voice.UssdModeType modeType, in String msg);
+  oneway void resendIncallMute(in android.hardware.radio.RadioIndicationType type);
+  oneway void srvccStateNotify(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.voice.SrvccState state);
+  oneway void stkCallControlAlphaNotify(in android.hardware.radio.RadioIndicationType type, in String alpha);
+  oneway void stkCallSetup(in android.hardware.radio.RadioIndicationType type, in long timeout);
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoiceResponse.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoiceResponse.aidl
new file mode 100644
index 0000000..7acc044
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoiceResponse.aidl
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.voice;
+@VintfStability
+interface IRadioVoiceResponse {
+  oneway void acceptCallResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void acknowledgeRequest(in int serial);
+  oneway void cancelPendingUssdResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void conferenceResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void dialResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void emergencyDialResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void exitEmergencyCallbackModeResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void explicitCallTransferResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void getCallForwardStatusResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.voice.CallForwardInfo[] callForwardInfos);
+  oneway void getCallWaitingResponse(in android.hardware.radio.RadioResponseInfo info, in boolean enable, in int serviceClass);
+  oneway void getClipResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.voice.ClipStatus status);
+  oneway void getClirResponse(in android.hardware.radio.RadioResponseInfo info, in int n, in int m);
+  oneway void getCurrentCallsResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.voice.Call[] calls);
+  oneway void getLastCallFailCauseResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.voice.LastCallFailCauseInfo failCauseinfo);
+  oneway void getMuteResponse(in android.hardware.radio.RadioResponseInfo info, in boolean enable);
+  oneway void getPreferredVoicePrivacyResponse(in android.hardware.radio.RadioResponseInfo info, in boolean enable);
+  oneway void getTtyModeResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.voice.TtyMode mode);
+  oneway void handleStkCallSetupRequestFromSimResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void hangupConnectionResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void hangupForegroundResumeBackgroundResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void hangupWaitingOrBackgroundResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void isVoNrEnabledResponse(in android.hardware.radio.RadioResponseInfo info, in boolean enable);
+  oneway void rejectCallResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void sendBurstDtmfResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void sendCdmaFeatureCodeResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void sendDtmfResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void sendUssdResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void separateConnectionResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setCallForwardResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setCallWaitingResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setClirResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setMuteResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setPreferredVoicePrivacyResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setTtyModeResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void setVoNrEnabledResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void startDtmfResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void stopDtmfResponse(in android.hardware.radio.RadioResponseInfo info);
+  oneway void switchWaitingOrHoldingAndActiveResponse(in android.hardware.radio.RadioResponseInfo info);
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/LastCallFailCause.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/LastCallFailCause.aidl
new file mode 100644
index 0000000..1740134
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/LastCallFailCause.aidl
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.voice;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum LastCallFailCause {
+  UNOBTAINABLE_NUMBER = 1,
+  NO_ROUTE_TO_DESTINATION = 3,
+  CHANNEL_UNACCEPTABLE = 6,
+  OPERATOR_DETERMINED_BARRING = 8,
+  NORMAL = 16,
+  BUSY = 17,
+  NO_USER_RESPONDING = 18,
+  NO_ANSWER_FROM_USER = 19,
+  CALL_REJECTED = 21,
+  NUMBER_CHANGED = 22,
+  PREEMPTION = 25,
+  DESTINATION_OUT_OF_ORDER = 27,
+  INVALID_NUMBER_FORMAT = 28,
+  FACILITY_REJECTED = 29,
+  RESP_TO_STATUS_ENQUIRY = 30,
+  NORMAL_UNSPECIFIED = 31,
+  CONGESTION = 34,
+  NETWORK_OUT_OF_ORDER = 38,
+  TEMPORARY_FAILURE = 41,
+  SWITCHING_EQUIPMENT_CONGESTION = 42,
+  ACCESS_INFORMATION_DISCARDED = 43,
+  REQUESTED_CIRCUIT_OR_CHANNEL_NOT_AVAILABLE = 44,
+  RESOURCES_UNAVAILABLE_OR_UNSPECIFIED = 47,
+  QOS_UNAVAILABLE = 49,
+  REQUESTED_FACILITY_NOT_SUBSCRIBED = 50,
+  INCOMING_CALLS_BARRED_WITHIN_CUG = 55,
+  BEARER_CAPABILITY_NOT_AUTHORIZED = 57,
+  BEARER_CAPABILITY_UNAVAILABLE = 58,
+  SERVICE_OPTION_NOT_AVAILABLE = 63,
+  BEARER_SERVICE_NOT_IMPLEMENTED = 65,
+  ACM_LIMIT_EXCEEDED = 68,
+  REQUESTED_FACILITY_NOT_IMPLEMENTED = 69,
+  ONLY_DIGITAL_INFORMATION_BEARER_AVAILABLE = 70,
+  SERVICE_OR_OPTION_NOT_IMPLEMENTED = 79,
+  INVALID_TRANSACTION_IDENTIFIER = 81,
+  USER_NOT_MEMBER_OF_CUG = 87,
+  INCOMPATIBLE_DESTINATION = 88,
+  INVALID_TRANSIT_NW_SELECTION = 91,
+  SEMANTICALLY_INCORRECT_MESSAGE = 95,
+  INVALID_MANDATORY_INFORMATION = 96,
+  MESSAGE_TYPE_NON_IMPLEMENTED = 97,
+  MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 98,
+  INFORMATION_ELEMENT_NON_EXISTENT = 99,
+  CONDITIONAL_IE_ERROR = 100,
+  MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 101,
+  RECOVERY_ON_TIMER_EXPIRED = 102,
+  PROTOCOL_ERROR_UNSPECIFIED = 111,
+  INTERWORKING_UNSPECIFIED = 127,
+  CALL_BARRED = 240,
+  FDN_BLOCKED = 241,
+  IMSI_UNKNOWN_IN_VLR = 242,
+  IMEI_NOT_ACCEPTED = 243,
+  DIAL_MODIFIED_TO_USSD = 244,
+  DIAL_MODIFIED_TO_SS = 245,
+  DIAL_MODIFIED_TO_DIAL = 246,
+  RADIO_OFF = 247,
+  OUT_OF_SERVICE = 248,
+  NO_VALID_SIM = 249,
+  RADIO_INTERNAL_ERROR = 250,
+  NETWORK_RESP_TIMEOUT = 251,
+  NETWORK_REJECT = 252,
+  RADIO_ACCESS_FAILURE = 253,
+  RADIO_LINK_FAILURE = 254,
+  RADIO_LINK_LOST = 255,
+  RADIO_UPLINK_FAILURE = 256,
+  RADIO_SETUP_FAILURE = 257,
+  RADIO_RELEASE_NORMAL = 258,
+  RADIO_RELEASE_ABNORMAL = 259,
+  ACCESS_CLASS_BLOCKED = 260,
+  NETWORK_DETACH = 261,
+  CDMA_LOCKED_UNTIL_POWER_CYCLE = 1000,
+  CDMA_DROP = 1001,
+  CDMA_INTERCEPT = 1002,
+  CDMA_REORDER = 1003,
+  CDMA_SO_REJECT = 1004,
+  CDMA_RETRY_ORDER = 1005,
+  CDMA_ACCESS_FAILURE = 1006,
+  CDMA_PREEMPTED = 1007,
+  CDMA_NOT_EMERGENCY = 1008,
+  CDMA_ACCESS_BLOCKED = 1009,
+  OEM_CAUSE_1 = 61441,
+  OEM_CAUSE_2 = 61442,
+  OEM_CAUSE_3 = 61443,
+  OEM_CAUSE_4 = 61444,
+  OEM_CAUSE_5 = 61445,
+  OEM_CAUSE_6 = 61446,
+  OEM_CAUSE_7 = 61447,
+  OEM_CAUSE_8 = 61448,
+  OEM_CAUSE_9 = 61449,
+  OEM_CAUSE_10 = 61450,
+  OEM_CAUSE_11 = 61451,
+  OEM_CAUSE_12 = 61452,
+  OEM_CAUSE_13 = 61453,
+  OEM_CAUSE_14 = 61454,
+  OEM_CAUSE_15 = 61455,
+  ERROR_UNSPECIFIED = 65535,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/LastCallFailCauseInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/LastCallFailCauseInfo.aidl
new file mode 100644
index 0000000..221acf7
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/LastCallFailCauseInfo.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.voice;
+@JavaDerive(toString=true) @VintfStability
+parcelable LastCallFailCauseInfo {
+  android.hardware.radio.voice.LastCallFailCause causeCode;
+  String vendorCause;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/SrvccState.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/SrvccState.aidl
new file mode 100644
index 0000000..864374b
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/SrvccState.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.voice;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum SrvccState {
+  HANDOVER_STARTED = 0,
+  HANDOVER_COMPLETED = 1,
+  HANDOVER_FAILED = 2,
+  HANDOVER_CANCELED = 3,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/SsInfoData.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/SsInfoData.aidl
new file mode 100644
index 0000000..f18b404
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/SsInfoData.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.voice;
+@JavaDerive(toString=true) @VintfStability
+parcelable SsInfoData {
+  int[] ssInfo;
+  const int SS_INFO_MAX = 4;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/StkCcUnsolSsResult.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/StkCcUnsolSsResult.aidl
new file mode 100644
index 0000000..50bb1fd
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/StkCcUnsolSsResult.aidl
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.voice;
+@JavaDerive(toString=true) @VintfStability
+parcelable StkCcUnsolSsResult {
+  int serviceType;
+  int requestType;
+  int teleserviceType;
+  int serviceClass;
+  android.hardware.radio.RadioError result;
+  android.hardware.radio.voice.SsInfoData[] ssInfo;
+  android.hardware.radio.voice.CfData[] cfData;
+  const int REQUEST_TYPE_ACTIVATION = 0;
+  const int REQUEST_TYPE_DEACTIVATION = 1;
+  const int REQUEST_TYPE_INTERROGATION = 2;
+  const int REQUEST_TYPE_REGISTRATION = 3;
+  const int REQUEST_TYPE_ERASURE = 4;
+  const int SERVICE_TYPE_CFU = 0;
+  const int SERVICE_TYPE_CF_BUSY = 1;
+  const int SERVICE_TYPE_CF_NO_REPLY = 2;
+  const int SERVICE_TYPE_CF_NOT_REACHABLE = 3;
+  const int SERVICE_TYPE_CF_ALL = 4;
+  const int SERVICE_TYPE_CF_ALL_CONDITIONAL = 5;
+  const int SERVICE_TYPE_CLIP = 6;
+  const int SERVICE_TYPE_CLIR = 7;
+  const int SERVICE_TYPE_COLP = 8;
+  const int SERVICE_TYPE_COLR = 9;
+  const int SERVICE_TYPE_WAIT = 10;
+  const int SERVICE_TYPE_BAOC = 11;
+  const int SERVICE_TYPE_BAOIC = 12;
+  const int SERVICE_TYPE_BAOIC_EXC_HOME = 13;
+  const int SERVICE_TYPE_BAIC = 14;
+  const int SERVICE_TYPE_BAIC_ROAMING = 15;
+  const int SERVICE_TYPE_ALL_BARRING = 16;
+  const int SERVICE_TYPE_OUTGOING_BARRING = 17;
+  const int SERVICE_TYPE_INCOMING_BARRING = 18;
+  const int TELESERVICE_TYPE_ALL_TELE_AND_BEARER_SERVICES = 0;
+  const int TELESERVICE_TYPE_ALL_TELESEVICES = 1;
+  const int TELESERVICE_TYPE_TELEPHONY = 2;
+  const int TELESERVICE_TYPE_ALL_DATA_TELESERVICES = 3;
+  const int TELESERVICE_TYPE_SMS_SERVICES = 4;
+  const int TELESERVICE_TYPE_ALL_TELESERVICES_EXCEPT_SMS = 5;
+  const int SUPP_SERVICE_CLASS_NONE = 0;
+  const int SUPP_SERVICE_CLASS_VOICE = 1;
+  const int SUPP_SERVICE_CLASS_DATA = 2;
+  const int SUPP_SERVICE_CLASS_FAX = 4;
+  const int SUPP_SERVICE_CLASS_SMS = 8;
+  const int SUPP_SERVICE_CLASS_DATA_SYNC = 16;
+  const int SUPP_SERVICE_CLASS_DATA_ASYNC = 32;
+  const int SUPP_SERVICE_CLASS_PACKET = 64;
+  const int SUPP_SERVICE_CLASS_PAD = 128;
+  const int SUPP_SERVICE_CLASS_MAX = 128;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/TtyMode.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/TtyMode.aidl
new file mode 100644
index 0000000..77417e8
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/TtyMode.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.voice;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum TtyMode {
+  OFF = 0,
+  FULL = 1,
+  HCO = 2,
+  VCO = 3,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/UssdModeType.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/UssdModeType.aidl
new file mode 100644
index 0000000..ad243d2
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/UssdModeType.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.voice;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum UssdModeType {
+  NOTIFY = 0,
+  REQUEST = 1,
+  NW_RELEASE = 2,
+  LOCAL_CLIENT = 3,
+  NOT_SUPPORTED = 4,
+  NW_TIMEOUT = 5,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/UusInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/UusInfo.aidl
new file mode 100644
index 0000000..9313760
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/UusInfo.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio.voice;
+@JavaDerive(toString=true) @VintfStability
+parcelable UusInfo {
+  int uusType;
+  int uusDcs;
+  String uusData;
+  const int UUS_DCS_USP = 0;
+  const int UUS_DCS_OSIHLP = 1;
+  const int UUS_DCS_X244 = 2;
+  const int UUS_DCS_RMCF = 3;
+  const int UUS_DCS_IA5C = 4;
+  const int UUS_TYPE_TYPE1_IMPLICIT = 0;
+  const int UUS_TYPE_TYPE1_REQUIRED = 1;
+  const int UUS_TYPE_TYPE1_NOT_REQUIRED = 2;
+  const int UUS_TYPE_TYPE2_REQUIRED = 3;
+  const int UUS_TYPE_TYPE2_NOT_REQUIRED = 4;
+  const int UUS_TYPE_TYPE3_REQUIRED = 5;
+  const int UUS_TYPE_TYPE3_NOT_REQUIRED = 6;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/AccessNetwork.aidl b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/AccessNetwork.aidl
new file mode 100644
index 0000000..8ce689f
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/AccessNetwork.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum AccessNetwork {
+  UNKNOWN = 0,
+  GERAN = 1,
+  UTRAN = 2,
+  EUTRAN = 3,
+  CDMA2000 = 4,
+  IWLAN = 5,
+  NGRAN = 6,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioAccessFamily.aidl b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioAccessFamily.aidl
new file mode 100644
index 0000000..ecc2a9b
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioAccessFamily.aidl
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum RadioAccessFamily {
+  UNKNOWN = 1,
+  GPRS = 2,
+  EDGE = 4,
+  UMTS = 8,
+  IS95A = 16,
+  IS95B = 32,
+  ONE_X_RTT = 64,
+  EVDO_0 = 128,
+  EVDO_A = 256,
+  HSDPA = 512,
+  HSUPA = 1024,
+  HSPA = 2048,
+  EVDO_B = 4096,
+  EHRPD = 8192,
+  LTE = 16384,
+  HSPAP = 32768,
+  GSM = 65536,
+  TD_SCDMA = 131072,
+  IWLAN = 262144,
+  LTE_CA = 524288,
+  NR = 1048576,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioConst.aidl b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioConst.aidl
new file mode 100644
index 0000000..b91bf03
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioConst.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio;
+@JavaDerive(toString=true) @VintfStability
+parcelable RadioConst {
+  const int MAX_RILDS = 3;
+  const int MAX_UUID_LENGTH = 64;
+  const int CARD_MAX_APPS = 8;
+  const int P2_CONSTANT_NO_P2 = -1;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioError.aidl b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioError.aidl
new file mode 100644
index 0000000..98606e5
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioError.aidl
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum RadioError {
+  NONE = 0,
+  RADIO_NOT_AVAILABLE = 1,
+  GENERIC_FAILURE = 2,
+  PASSWORD_INCORRECT = 3,
+  SIM_PIN2 = 4,
+  SIM_PUK2 = 5,
+  REQUEST_NOT_SUPPORTED = 6,
+  CANCELLED = 7,
+  OP_NOT_ALLOWED_DURING_VOICE_CALL = 8,
+  OP_NOT_ALLOWED_BEFORE_REG_TO_NW = 9,
+  SMS_SEND_FAIL_RETRY = 10,
+  SIM_ABSENT = 11,
+  SUBSCRIPTION_NOT_AVAILABLE = 12,
+  MODE_NOT_SUPPORTED = 13,
+  FDN_CHECK_FAILURE = 14,
+  ILLEGAL_SIM_OR_ME = 15,
+  MISSING_RESOURCE = 16,
+  NO_SUCH_ELEMENT = 17,
+  DIAL_MODIFIED_TO_USSD = 18,
+  DIAL_MODIFIED_TO_SS = 19,
+  DIAL_MODIFIED_TO_DIAL = 20,
+  USSD_MODIFIED_TO_DIAL = 21,
+  USSD_MODIFIED_TO_SS = 22,
+  USSD_MODIFIED_TO_USSD = 23,
+  SS_MODIFIED_TO_DIAL = 24,
+  SS_MODIFIED_TO_USSD = 25,
+  SUBSCRIPTION_NOT_SUPPORTED = 26,
+  SS_MODIFIED_TO_SS = 27,
+  LCE_NOT_SUPPORTED = 36,
+  NO_MEMORY = 37,
+  INTERNAL_ERR = 38,
+  SYSTEM_ERR = 39,
+  MODEM_ERR = 40,
+  INVALID_STATE = 41,
+  NO_RESOURCES = 42,
+  SIM_ERR = 43,
+  INVALID_ARGUMENTS = 44,
+  INVALID_SIM_STATE = 45,
+  INVALID_MODEM_STATE = 46,
+  INVALID_CALL_ID = 47,
+  NO_SMS_TO_ACK = 48,
+  NETWORK_ERR = 49,
+  REQUEST_RATE_LIMITED = 50,
+  SIM_BUSY = 51,
+  SIM_FULL = 52,
+  NETWORK_REJECT = 53,
+  OPERATION_NOT_ALLOWED = 54,
+  EMPTY_RECORD = 55,
+  INVALID_SMS_FORMAT = 56,
+  ENCODING_ERR = 57,
+  INVALID_SMSC_ADDRESS = 58,
+  NO_SUCH_ENTRY = 59,
+  NETWORK_NOT_READY = 60,
+  NOT_PROVISIONED = 61,
+  NO_SUBSCRIPTION = 62,
+  NO_NETWORK_FOUND = 63,
+  DEVICE_IN_USE = 64,
+  ABORTED = 65,
+  INVALID_RESPONSE = 66,
+  OEM_ERROR_1 = 501,
+  OEM_ERROR_2 = 502,
+  OEM_ERROR_3 = 503,
+  OEM_ERROR_4 = 504,
+  OEM_ERROR_5 = 505,
+  OEM_ERROR_6 = 506,
+  OEM_ERROR_7 = 507,
+  OEM_ERROR_8 = 508,
+  OEM_ERROR_9 = 509,
+  OEM_ERROR_10 = 510,
+  OEM_ERROR_11 = 511,
+  OEM_ERROR_12 = 512,
+  OEM_ERROR_13 = 513,
+  OEM_ERROR_14 = 514,
+  OEM_ERROR_15 = 515,
+  OEM_ERROR_16 = 516,
+  OEM_ERROR_17 = 517,
+  OEM_ERROR_18 = 518,
+  OEM_ERROR_19 = 519,
+  OEM_ERROR_20 = 520,
+  OEM_ERROR_21 = 521,
+  OEM_ERROR_22 = 522,
+  OEM_ERROR_23 = 523,
+  OEM_ERROR_24 = 524,
+  OEM_ERROR_25 = 525,
+  SIMULTANEOUS_SMS_AND_CALL_NOT_ALLOWED = 67,
+  ACCESS_BARRED = 68,
+  BLOCKED_DUE_TO_CALL = 69,
+  RF_HARDWARE_ISSUE = 70,
+  NO_RF_CALIBRATION_INFO = 71,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioIndicationType.aidl b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioIndicationType.aidl
new file mode 100644
index 0000000..54ea3a4
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioIndicationType.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum RadioIndicationType {
+  UNSOLICITED = 0,
+  UNSOLICITED_ACK_EXP = 1,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioResponseInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioResponseInfo.aidl
new file mode 100644
index 0000000..b2a7a06
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioResponseInfo.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio;
+@JavaDerive(toString=true) @VintfStability
+parcelable RadioResponseInfo {
+  android.hardware.radio.RadioResponseType type;
+  int serial;
+  android.hardware.radio.RadioError error;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioResponseInfoModem.aidl b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioResponseInfoModem.aidl
new file mode 100644
index 0000000..37ed7bb
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioResponseInfoModem.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio;
+@JavaDerive(toString=true) @VintfStability
+parcelable RadioResponseInfoModem {
+  android.hardware.radio.RadioResponseType type;
+  int serial;
+  android.hardware.radio.RadioError error;
+  boolean isEnabled;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioResponseType.aidl b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioResponseType.aidl
new file mode 100644
index 0000000..5cd99c4
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioResponseType.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum RadioResponseType {
+  SOLICITED = 0,
+  SOLICITED_ACK = 1,
+  SOLICITED_ACK_EXP = 2,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioTechnology.aidl b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioTechnology.aidl
new file mode 100644
index 0000000..9dad0a4
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioTechnology.aidl
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum RadioTechnology {
+  UNKNOWN = 0,
+  GPRS = 1,
+  EDGE = 2,
+  UMTS = 3,
+  IS95A = 4,
+  IS95B = 5,
+  ONE_X_RTT = 6,
+  EVDO_0 = 7,
+  EVDO_A = 8,
+  HSDPA = 9,
+  HSUPA = 10,
+  HSPA = 11,
+  EVDO_B = 12,
+  EHRPD = 13,
+  LTE = 14,
+  HSPAP = 15,
+  GSM = 16,
+  TD_SCDMA = 17,
+  IWLAN = 18,
+  LTE_CA = 19,
+  NR = 20,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioTechnologyFamily.aidl b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioTechnologyFamily.aidl
new file mode 100644
index 0000000..e6fdce2
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioTechnologyFamily.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.radio;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum RadioTechnologyFamily {
+  THREE_GPP = 0,
+  THREE_GPP2 = 1,
+}
diff --git a/radio/aidl/android/hardware/radio/AccessNetwork.aidl b/radio/aidl/android/hardware/radio/AccessNetwork.aidl
new file mode 100644
index 0000000..2885642
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/AccessNetwork.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio;
+
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum AccessNetwork {
+    /**
+     * Unknown access network
+     */
+    UNKNOWN,
+    /**
+     * GSM EDGE Radio Access Network
+     */
+    GERAN,
+    /**
+     * Universal Terrestrial Radio Access Network
+     */
+    UTRAN,
+    /**
+     * Evolved Universal Terrestrial Radio Access Network
+     */
+    EUTRAN,
+    /**
+     * CDMA 2000 network
+     */
+    CDMA2000,
+    /**
+     * Interworking Wireless LAN
+     */
+    IWLAN,
+    /**
+     * Next-Generation Radio Access Network (NGRAN).
+     * Note NGRAN is only for standalone mode. Non-standalone mode uses AccessNetwork EUTRAN.
+     */
+    NGRAN,
+}
diff --git a/radio/aidl/android/hardware/radio/RadioAccessFamily.aidl b/radio/aidl/android/hardware/radio/RadioAccessFamily.aidl
new file mode 100644
index 0000000..6cd0a95
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/RadioAccessFamily.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio;
+
+import android.hardware.radio.RadioTechnology;
+
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum RadioAccessFamily {
+    UNKNOWN = 1 << RadioTechnology.UNKNOWN,
+    GPRS = 1 << RadioTechnology.GPRS,
+    EDGE = 1 << RadioTechnology.EDGE,
+    UMTS = 1 << RadioTechnology.UMTS,
+    IS95A = 1 << RadioTechnology.IS95A,
+    IS95B = 1 << RadioTechnology.IS95B,
+    ONE_X_RTT = 1 << RadioTechnology.ONE_X_RTT,
+    EVDO_0 = 1 << RadioTechnology.EVDO_0,
+    EVDO_A = 1 << RadioTechnology.EVDO_A,
+    HSDPA = 1 << RadioTechnology.HSDPA,
+    HSUPA = 1 << RadioTechnology.HSUPA,
+    HSPA = 1 << RadioTechnology.HSPA,
+    EVDO_B = 1 << RadioTechnology.EVDO_B,
+    EHRPD = 1 << RadioTechnology.EHRPD,
+    LTE = 1 << RadioTechnology.LTE,
+    HSPAP = 1 << RadioTechnology.HSPAP,
+    GSM = 1 << RadioTechnology.GSM,
+    TD_SCDMA = 1 << RadioTechnology.TD_SCDMA,
+    IWLAN = 1 << RadioTechnology.IWLAN,
+    LTE_CA = 1 << RadioTechnology.LTE_CA,
+    /**
+     * 5G NR. This is only use in 5G Standalone mode.
+     */
+    NR = 1 << RadioTechnology.NR,
+}
diff --git a/radio/aidl/android/hardware/radio/RadioConst.aidl b/radio/aidl/android/hardware/radio/RadioConst.aidl
new file mode 100644
index 0000000..6591ef1
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/RadioConst.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable RadioConst {
+    const int MAX_RILDS = 3;
+    const int MAX_UUID_LENGTH = 64;
+    const int CARD_MAX_APPS = 8;
+    /**
+     * No P2 value is provided
+     */
+    const int P2_CONSTANT_NO_P2 = -1;
+}
diff --git a/radio/aidl/android/hardware/radio/RadioError.aidl b/radio/aidl/android/hardware/radio/RadioError.aidl
new file mode 100644
index 0000000..ae58a0e
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/RadioError.aidl
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio;
+
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum RadioError {
+    /**
+     * Success
+     */
+    NONE = 0,
+    /**
+     * If radio did not start or is resetting
+     */
+    RADIO_NOT_AVAILABLE = 1,
+    GENERIC_FAILURE = 2,
+    /**
+     * For PIN/PIN2 methods only
+     */
+    PASSWORD_INCORRECT = 3,
+    /**
+     * Operation requires SIM PIN2 to be entered
+     */
+    SIM_PIN2 = 4,
+    /**
+     * Operation requires SIM PUK2 to be entered
+     */
+    SIM_PUK2 = 5,
+    REQUEST_NOT_SUPPORTED = 6,
+    CANCELLED = 7,
+    /**
+     * Data ops are not allowed during voice call on a Class C GPRS device
+     */
+    OP_NOT_ALLOWED_DURING_VOICE_CALL = 8,
+    /**
+     * Data ops are not allowed before device registers in network
+     */
+    OP_NOT_ALLOWED_BEFORE_REG_TO_NW = 9,
+    /**
+     * Fail to send SMS and need to retry
+     */
+    SMS_SEND_FAIL_RETRY = 10,
+    /**
+     * Fail to set the location where CDMA subscription shall be retrieved because of SIM or
+     * RUIM card absent
+     */
+    SIM_ABSENT = 11,
+    /**
+     * Fail to find CDMA subscription from specified location
+     */
+    SUBSCRIPTION_NOT_AVAILABLE = 12,
+    /**
+     * HW does not support preferred network type
+     */
+    MODE_NOT_SUPPORTED = 13,
+    /**
+     * Command failed becausee recipient is not on FDN list
+     */
+    FDN_CHECK_FAILURE = 14,
+    /**
+     * Network selection failed due to illegal SIM or ME
+     */
+    ILLEGAL_SIM_OR_ME = 15,
+    /**
+     * No logical channel available
+     */
+    MISSING_RESOURCE = 16,
+    /**
+     * Application not found on SIM
+     */
+    NO_SUCH_ELEMENT = 17,
+    /**
+     * DIAL request modified to USSD
+     */
+    DIAL_MODIFIED_TO_USSD = 18,
+    /**
+     * DIAL request modified to SS
+     */
+    DIAL_MODIFIED_TO_SS = 19,
+    /**
+     * DIAL request modified to DIAL with different data
+     */
+    DIAL_MODIFIED_TO_DIAL = 20,
+    /**
+     * USSD request modified to DIAL
+     */
+    USSD_MODIFIED_TO_DIAL = 21,
+    /**
+     * USSD request modified to SS
+     */
+    USSD_MODIFIED_TO_SS = 22,
+    /**
+     * USSD request modified to different USSD request
+     */
+    USSD_MODIFIED_TO_USSD = 23,
+    /**
+     * SS request modified to DIAL
+     */
+    SS_MODIFIED_TO_DIAL = 24,
+    /**
+     * SS request modified to USSD
+     */
+    SS_MODIFIED_TO_USSD = 25,
+    /**
+     * Subscription not supported by RIL
+     */
+    SUBSCRIPTION_NOT_SUPPORTED = 26,
+    /**
+     * SS request modified to different SS request
+     */
+    SS_MODIFIED_TO_SS = 27,
+    /**
+     * LCE service not supported(36 in RILConstants.java)
+     */
+    LCE_NOT_SUPPORTED = 36,
+    /**
+     * Not sufficieent memory to process the request
+     */
+    NO_MEMORY = 37,
+    /**
+     * Modem hit unexpected error scenario while handling this request
+     */
+    INTERNAL_ERR = 38,
+    /**
+     * Hit platform or system error
+     */
+    SYSTEM_ERR = 39,
+    /**
+     * Vendor RIL got unexpected or incorrect response from modem for this request
+     */
+    MODEM_ERR = 40,
+    /**
+     * Unexpected request for the current state
+     */
+    INVALID_STATE = 41,
+    /**
+     * Not sufficient resource to process the request
+     */
+    NO_RESOURCES = 42,
+    /**
+     * Received error from SIM card
+     */
+    SIM_ERR = 43,
+    /**
+     * Received invalid arguments in request
+     */
+    INVALID_ARGUMENTS = 44,
+    /**
+     * Cannot process the request in current SIM state
+     */
+    INVALID_SIM_STATE = 45,
+    /**
+     * Cannot process the request in current modem state
+     */
+    INVALID_MODEM_STATE = 46,
+    /**
+     * Received invalid call ID in request
+     */
+    INVALID_CALL_ID = 47,
+    /**
+     * ACK received when there is no SMS to ack
+     */
+    NO_SMS_TO_ACK = 48,
+    /**
+     * Received error from network
+     */
+    NETWORK_ERR = 49,
+    /**
+     * Operation denied due to overly-frequent requests
+     */
+    REQUEST_RATE_LIMITED = 50,
+    /**
+     * SIM is busy
+     */
+    SIM_BUSY = 51,
+    /**
+     * The target EF is full
+     */
+    SIM_FULL = 52,
+    /**
+     * Request is rejected by network
+     */
+    NETWORK_REJECT = 53,
+    /**
+     * Not allowed the request not
+     */
+    OPERATION_NOT_ALLOWED = 54,
+    /**
+     * The request record is empty
+     */
+    EMPTY_RECORD = 55,
+    /**
+     * Invalid SMS format
+     */
+    INVALID_SMS_FORMAT = 56,
+    /**
+     * Message not encoded properly
+     */
+    ENCODING_ERR = 57,
+    /**
+     * SMSC addrss specified is invalid
+     */
+    INVALID_SMSC_ADDRESS = 58,
+    /**
+     * No such entry present to perform the request
+     */
+    NO_SUCH_ENTRY = 59,
+    /**
+     * Network is not ready to perform the request
+     */
+    NETWORK_NOT_READY = 60,
+    /**
+     * Device does not have this value provisioned
+     */
+    NOT_PROVISIONED = 61,
+    /**
+     * Device does not have subscription
+     */
+    NO_SUBSCRIPTION = 62,
+    /**
+     * Network cannot be found
+     */
+    NO_NETWORK_FOUND = 63,
+    /**
+     * Operation cannot be performed because the device is currently in use
+     */
+    DEVICE_IN_USE = 64,
+    /**
+     * Operation aborted
+     */
+    ABORTED = 65,
+    /**
+     * Response from vendor had invalid data
+     */
+    INVALID_RESPONSE = 66,
+    OEM_ERROR_1 = 501,
+    OEM_ERROR_2 = 502,
+    OEM_ERROR_3 = 503,
+    OEM_ERROR_4 = 504,
+    OEM_ERROR_5 = 505,
+    OEM_ERROR_6 = 506,
+    OEM_ERROR_7 = 507,
+    OEM_ERROR_8 = 508,
+    OEM_ERROR_9 = 509,
+    OEM_ERROR_10 = 510,
+    OEM_ERROR_11 = 511,
+    OEM_ERROR_12 = 512,
+    OEM_ERROR_13 = 513,
+    OEM_ERROR_14 = 514,
+    OEM_ERROR_15 = 515,
+    OEM_ERROR_16 = 516,
+    OEM_ERROR_17 = 517,
+    OEM_ERROR_18 = 518,
+    OEM_ERROR_19 = 519,
+    OEM_ERROR_20 = 520,
+    OEM_ERROR_21 = 521,
+    OEM_ERROR_22 = 522,
+    OEM_ERROR_23 = 523,
+    OEM_ERROR_24 = 524,
+    OEM_ERROR_25 = 525,
+    /**
+     * 1X voice and SMS are not allowed simulteneously.
+     */
+    SIMULTANEOUS_SMS_AND_CALL_NOT_ALLOWED = 67,
+    /**
+     * Access is barred.
+     */
+    ACCESS_BARRED = 68,
+    /**
+     * SMS is blocked due to call control, e.g., resource unavailable
+     * in the SMR entity.
+     */
+    BLOCKED_DUE_TO_CALL = 69,
+    /**
+     * Returned from setRadioPowerResponse when detecting RF HW issues. Some RF Front-End (RFFE)
+     * components like antenna are considered critical for modem to provide telephony service.
+     * This RadioError is used when modem detect such RFFE problem.
+     */
+    RF_HARDWARE_ISSUE = 70,
+    /**
+     * Returned from setRadioPowerResponse when detecting no RF calibration issue.
+     * Unlike RF_HARDWARE_ISSUE, this is a SW problem and no HW repair is needed.
+     */
+    NO_RF_CALIBRATION_INFO = 71,
+}
diff --git a/radio/aidl/android/hardware/radio/RadioIndicationType.aidl b/radio/aidl/android/hardware/radio/RadioIndicationType.aidl
new file mode 100644
index 0000000..2dcc492
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/RadioIndicationType.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio;
+
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum RadioIndicationType {
+    UNSOLICITED,
+    UNSOLICITED_ACK_EXP,
+}
diff --git a/radio/aidl/android/hardware/radio/RadioResponseInfo.aidl b/radio/aidl/android/hardware/radio/RadioResponseInfo.aidl
new file mode 100644
index 0000000..f70a3fe
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/RadioResponseInfo.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio;
+
+import android.hardware.radio.RadioError;
+import android.hardware.radio.RadioResponseType;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable RadioResponseInfo {
+    /**
+     * Response type
+     */
+    RadioResponseType type;
+    /**
+     * Serial number of the request
+     */
+    int serial;
+    /**
+     * Response error
+     */
+    RadioError error;
+}
diff --git a/radio/aidl/android/hardware/radio/RadioResponseInfoModem.aidl b/radio/aidl/android/hardware/radio/RadioResponseInfoModem.aidl
new file mode 100644
index 0000000..13abfb9
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/RadioResponseInfoModem.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio;
+
+import android.hardware.radio.RadioError;
+import android.hardware.radio.RadioResponseType;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable RadioResponseInfoModem {
+    /**
+     * Response type
+     */
+    RadioResponseType type;
+    /**
+     * Serial number of the request
+     */
+    int serial;
+    /**
+     * Response error
+     */
+    RadioError error;
+    /**
+     * Whether the modem is enabled or not
+     */
+    boolean isEnabled;
+}
diff --git a/radio/aidl/android/hardware/radio/RadioResponseType.aidl b/radio/aidl/android/hardware/radio/RadioResponseType.aidl
new file mode 100644
index 0000000..cd4a305
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/RadioResponseType.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio;
+
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum RadioResponseType {
+    SOLICITED,
+    SOLICITED_ACK,
+    SOLICITED_ACK_EXP,
+}
diff --git a/radio/aidl/android/hardware/radio/RadioTechnology.aidl b/radio/aidl/android/hardware/radio/RadioTechnology.aidl
new file mode 100644
index 0000000..917cb16
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/RadioTechnology.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio;
+
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum RadioTechnology {
+    UNKNOWN,
+    GPRS,
+    EDGE,
+    UMTS,
+    IS95A,
+    IS95B,
+    ONE_X_RTT,
+    EVDO_0,
+    EVDO_A,
+    HSDPA,
+    HSUPA,
+    HSPA,
+    EVDO_B,
+    EHRPD,
+    LTE,
+    /**
+     * HSPA+
+     */
+    HSPAP,
+    /**
+     * Only supports voice
+     */
+    GSM,
+    TD_SCDMA,
+    IWLAN,
+    LTE_CA,
+    /**
+     * 5G NR. This is only used in 5G Standalone mode.
+     */
+    NR,
+}
diff --git a/radio/aidl/android/hardware/radio/RadioTechnologyFamily.aidl b/radio/aidl/android/hardware/radio/RadioTechnologyFamily.aidl
new file mode 100644
index 0000000..a2b989d
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/RadioTechnologyFamily.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio;
+
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum RadioTechnologyFamily {
+    /**
+     * 3GPP Technologies - GSM, WCDMA
+     */
+    THREE_GPP,
+    /**
+     * 3GPP2 Technologies - CDMA
+     */
+    THREE_GPP2,
+}
diff --git a/radio/aidl/android/hardware/radio/config/IRadioConfig.aidl b/radio/aidl/android/hardware/radio/config/IRadioConfig.aidl
new file mode 100644
index 0000000..85c2cee
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/config/IRadioConfig.aidl
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *
+ * This interface is used by telephony and telecom to talk to cellular radio for the purpose of
+ * radio configuration, and it is not associated with any specific modem or slot.
+ * All the functions have minimum one parameter:
+ * serial: which corresponds to serial no. of request. Serial numbers must only be memorized for the
+ * duration of a method call. If clients provide colliding serials (including passing the same
+ * serial to different methods), multiple responses (one for each method call) must still be served.
+ */
+
+package android.hardware.radio.config;
+
+import android.hardware.radio.config.IRadioConfigIndication;
+import android.hardware.radio.config.IRadioConfigResponse;
+import android.hardware.radio.config.SlotPortMapping;
+
+@VintfStability
+oneway interface IRadioConfig {
+    /**
+     * Gets the available Radio Hal capabilities on the current device.
+     *
+     * This is called once per device boot up.
+     *
+     * @param serial Serial number of request
+     *
+     * Response callback is
+     * IRadioConfigResponse.getHalDeviceCapabilitiesResponse()
+     */
+    void getHalDeviceCapabilities(in int serial);
+
+    /**
+     * Get the number of live modems (i.e modems that are
+     * enabled and actively working as part of a working telephony stack)
+     *
+     * Note: in order to get the overall number of modems available on the phone,
+     * refer to getPhoneCapability API
+     *
+     * @param serial Serial number of request.
+     *
+     * Response callback is IRadioConfigResponse.getNumOfLiveModemsResponse() which
+     * will return <byte>.
+     */
+    void getNumOfLiveModems(in int serial);
+
+    /**
+     * Request current phone capability.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response callback is IRadioResponse.getPhoneCapabilityResponse() which
+     * will return <PhoneCapability>.
+     */
+    void getPhoneCapability(in int serial);
+
+    /**
+     * Get SIM Slot status.
+     *
+     * Request provides the slot status of all active and inactive SIM slots and whether card is
+     * present in the slots or not.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response callback is IRadioConfigResponse.getSimSlotsStatusResponse()
+     */
+    void getSimSlotsStatus(in int serial);
+
+    /**
+     * Set modems configurations by specifying the number of live modems (i.e modems that are
+     * enabled and actively working as part of a working telephony stack).
+     *
+     * Example: this interface can be used to switch to single/multi sim mode by specifying
+     * the number of live modems as 1, 2, etc
+     *
+     * Note: by setting the number of live modems in this API, that number of modems will
+     * subsequently get enabled/disabled
+     *
+     * @param serial serial number of request.
+     * @param modemsConfig byte object including the number of live modems
+     *
+     * Response callback is IRadioResponse.setNumOfLiveModemsResponse()
+     */
+    void setNumOfLiveModems(in int serial, in byte numOfLiveModems);
+
+    /**
+     * Set preferred data modem Id.
+     * In a multi-SIM device, notify modem layer which logical modem will be used primarily
+     * for data. It helps modem with resource optimization and decisions of what data connections
+     * should be satisfied.
+     *
+     * @param serial Serial number of request.
+     * @param modem Id the logical modem ID, which should match one of modem IDs returned
+     * from getPhoneCapability().
+     *
+     * Response callback is IRadioConfigResponse.setPreferredDataModemResponse()
+     */
+    void setPreferredDataModem(in int serial, in byte modemId);
+
+    /**
+     * Set response functions for radio config requests & radio config indications.
+     *
+     * @param radioConfigResponse Object containing radio config response functions
+     * @param radioConfigIndication Object containing radio config indications
+     */
+    void setResponseFunctions(in IRadioConfigResponse radioConfigResponse,
+            in IRadioConfigIndication radioConfigIndication);
+
+    /**
+     * Set SIM Slot mapping.
+     *
+     * Maps the logical slots to the SlotPortMapping which consist of both physical slot id and port
+     * id. Logical slot is the slot that is seen by modem. Physical slot is the actual physical
+     * slot. PortId is the id (enumerated value) for the associated port available on the SIM. Each
+     * physical slot can have multiple ports which enables multi-enabled profile(MEP). If eUICC
+     * physical slot supports 2 ports, then the portId is numbered 0,1 and if eUICC2 supports 4
+     * ports then the portID is numbered 0,1,2,3. Each portId is unique within a UICC physical slot
+     * but not necessarily unique across UICC’s. SEP(Single enabled profile) eUICC and non-eUICC
+     * will only have portId 0.
+     *
+     * Logical slots that are already mapped to the requested SlotPortMapping are not impacted.
+     *
+     * Example no. of logical slots 1 and physical slots 2 do not support MEP, each physical slot
+     * has one port:
+     * The only logical slot (index 0) can be mapped to first physical slot (value 0), port(index
+     * 0). or second
+     * physical slot(value 1), port (index 0), while the other physical slot remains unmapped and
+     * inactive.
+     * slotMap[0] = SlotPortMapping{0 //physical slot//, 0 //port//}
+     * slotMap[0] = SlotPortMapping{1 //physical slot//, 0 //port//}
+     *
+     * Example no. of logical slots 2 and physical slots 2 supports MEP with 2 ports available:
+     * Each logical slot must be mapped to a port (physical slot and port combination).
+     * First logical slot (index 0) can be mapped to physical slot 1 and the second logical slot
+     * can be mapped to either port from physical slot 2.
+     *
+     * slotMap[0] = SlotPortMapping{0, 0} and slotMap[1] = SlotPortMapping{1, 0} or
+     * slotMap[0] = SlotPortMapping{0, 0} and slotMap[1] = SlotPortMapping{1, 1}
+     *
+     * or the other way around, the second logical slot(index 1) can be mapped to physical slot 1
+     * and the first logical slot can be mapped to either port from physical slot 2.
+     *
+     * slotMap[1] = SlotPortMapping{0, 0} and slotMap[0] = SlotPortMapping{1, 0} or
+     * slotMap[1] = SlotPortMapping{0, 0} and slotMap[0] = SlotPortMapping{1, 1}
+     *
+     * another possible mapping is each logical slot maps to each port of physical slot 2 and there
+     * is no active logical modem mapped to physical slot 1.
+     *
+     * slotMap[0] = SlotPortMapping{1, 0} and slotMap[1] = SlotPortMapping{1, 1} or
+     * slotMap[0] = SlotPortMapping{1, 1} and slotMap[1] = SlotPortMapping{1, 0}
+     *
+     * @param serial Serial number of request
+     * @param slotMap Logical to physical slot and port mapping.
+     *        Index is mapping to logical slot and value to physical slot and port id, need to
+     *        provide all the slots mapping when sending request in case of multi slot device.
+     *
+     *        EX: SlotPortMapping(physical slot, port id)
+     *        index 0 is the first logical_slot number of logical slots is equal to number of Radio
+     *        instances and number of physical slots is equal to size of slotStatus in
+     *        getSimSlotsStatusResponse
+     *
+     * Response callback is IRadioConfigResponse.setSimSlotsMappingResponse()
+     */
+    void setSimSlotsMapping(in int serial, in SlotPortMapping[] slotMap);
+}
diff --git a/radio/aidl/android/hardware/radio/config/IRadioConfigIndication.aidl b/radio/aidl/android/hardware/radio/config/IRadioConfigIndication.aidl
new file mode 100644
index 0000000..abf55f1
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/config/IRadioConfigIndication.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.config;
+
+import android.hardware.radio.config.SimSlotStatus;
+
+/**
+ * Interface declaring unsolicited radio config indications.
+ */
+@VintfStability
+oneway interface IRadioConfigIndication {
+    /**
+     * Indicates SIM slot status change.
+     *
+     * This indication must be sent by the modem whenever there is any slot status change, even the
+     * slot is inactive. For example, this indication must be triggered if a SIM card is inserted
+     * into an inactive slot.
+     *
+     * @param type Type of radio indication
+     * @param slotStatus new slot status info with size equals to the number of physical slots on
+     *        the device
+     */
+    void simSlotsStatusChanged(
+            in android.hardware.radio.RadioIndicationType type, in SimSlotStatus[] slotStatus);
+}
diff --git a/radio/aidl/android/hardware/radio/config/IRadioConfigResponse.aidl b/radio/aidl/android/hardware/radio/config/IRadioConfigResponse.aidl
new file mode 100644
index 0000000..929f02d
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/config/IRadioConfigResponse.aidl
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.config;
+
+import android.hardware.radio.config.PhoneCapability;
+import android.hardware.radio.config.SimSlotStatus;
+
+/**
+ * Interface declaring response functions to solicited radio config requests.
+ */
+@VintfStability
+oneway interface IRadioConfigResponse {
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param modemReducedFeatureSet1 True indicates that the modem does NOT support the following
+     *        features.
+     *        - Providing either LinkCapacityEstimate:secondaryDownlinkCapacityKbps
+     *          or LinkCapacityEstimate:secondaryUplinkCapacityKbps when given from
+     *          RadioIndication:currentLinkCapacityEstimate
+     *        - Calling IRadio.setNrDualConnectivityState or querying
+     *          IRadio.isNrDualConnectivityEnabled
+     *        - Requesting IRadio.setDataThrottling()
+     *        - Providing SlicingConfig through getSlicingConfig()
+     *        - Providing PhysicalChannelConfig through
+     *          IRadioIndication.currentPhysicalChannelConfigs_1_6()
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     */
+    void getHalDeviceCapabilitiesResponse(
+            in android.hardware.radio.RadioResponseInfo info, in boolean modemReducedFeatureSet1);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param numOfLiveModems <byte> indicate the number of live modems i.e. modems that
+     *        are enabled and actively working as part of a working connectivity stack
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void getNumOfLiveModemsResponse(
+            in android.hardware.radio.RadioResponseInfo info, in byte numOfLiveModems);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param phoneCapability <PhoneCapability> it defines modem's capability for example
+     *        how many logical modems it has, how many data connections it supports.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     */
+    void getPhoneCapabilityResponse(
+            in android.hardware.radio.RadioResponseInfo info, in PhoneCapability phoneCapability);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param slotStatus Sim slot struct containing all the physical SIM slots info with size
+     *        equal to the number of physical slots on the device
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:NO_MEMORY
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:MODEM_ERR
+     */
+    void getSimSlotsStatusResponse(
+            in android.hardware.radio.RadioResponseInfo info, in SimSlotStatus[] slotStatus);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:INVALID_ARGUMENTS
+     */
+    void setNumOfLiveModemsResponse(in android.hardware.radio.RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     */
+    void setPreferredDataModemResponse(in android.hardware.radio.RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:NO_MEMORY
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:MODEM_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     */
+    void setSimSlotsMappingResponse(in android.hardware.radio.RadioResponseInfo info);
+}
diff --git a/radio/aidl/android/hardware/radio/config/PhoneCapability.aidl b/radio/aidl/android/hardware/radio/config/PhoneCapability.aidl
new file mode 100644
index 0000000..8e4f338
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/config/PhoneCapability.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.config;
+
+/**
+ * Phone capability which describes the data connection capability of modem.
+ * It's used to evaluate possible phone config change, for example from single
+ * SIM device to multi-SIM device.
+ */
+@VintfStability
+@JavaDerive(toString=true)
+parcelable PhoneCapability {
+    /**
+     * maxActiveData defines how many logical modems can have
+     * PS attached simultaneously. For example, for L+L modem it
+     * should be 2.
+     */
+    byte maxActiveData;
+    /**
+     * maxActiveData defines how many logical modems can have
+     * internet PDN connections simultaneously. For example, for L+L
+     * DSDS modem it’s 1, and for DSDA modem it’s 2.
+     */
+    byte maxActiveInternetData;
+    /**
+     * Whether modem supports both internet PDN up so
+     * that we can do ping test before tearing down the
+     * other one.
+     */
+    boolean isInternetLingeringSupported;
+    /**
+     * List of logical modem IDs.
+     */
+    byte[] logicalModemIds;
+}
diff --git a/radio/aidl/android/hardware/radio/config/SimPortInfo.aidl b/radio/aidl/android/hardware/radio/config/SimPortInfo.aidl
new file mode 100644
index 0000000..db24719
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/config/SimPortInfo.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.config;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable SimPortInfo {
+    /**
+     * Integrated Circuit Card IDentifier (ICCID) is unique identifier of the SIM card. File is
+     * located in the SIM card at EFiccid (0x2FE2) as per ETSI 102.221. The ICCID is defined by
+     * the ITU-T recommendation E.118 ISO/IEC 7816.
+     *
+     * This data is applicable only when cardState is CardStatus.STATE_PRESENT.
+     *
+     * This is the ICCID of the currently enabled profile. If no profile is enabled,
+     * then it will contain the default boot profile’s ICCID.
+     * If the EFiccid does not exist in the default boot profile, it will be null.
+     */
+    String iccId;
+    /**
+     * Logical slot id is identifier of the active slot
+     */
+    int logicalSlotId;
+    /**
+     * Port active status in the slot.
+     * Inactive means logical modem is no longer associated to the port.
+     * Active means logical modem is associated to the port.
+     */
+    boolean portActive;
+}
diff --git a/radio/aidl/android/hardware/radio/config/SimSlotStatus.aidl b/radio/aidl/android/hardware/radio/config/SimSlotStatus.aidl
new file mode 100644
index 0000000..748660f
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/config/SimSlotStatus.aidl
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.config;
+
+import android.hardware.radio.config.SimPortInfo;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable SimSlotStatus {
+    /**
+     * Card state in the physical slot. Values are CardStatus.[STATE_ABSENT, STATE_PRESENT,
+     * STATE_ERROR, STATE_RESTRICTED].
+     */
+    int cardState;
+    /**
+     * An Answer To Reset (ATR) is a message output by a Smart Card conforming to ISO/IEC 7816
+     * standards, following electrical reset of the card's chip. The ATR conveys information about
+     * the communication parameters proposed by the card, and the card's nature and state.
+     *
+     * This data is applicable only when cardState is CardStatus.STATE_PRESENT.
+     */
+    String atr;
+    /**
+     * The EID is the eUICC identifier. The EID shall be stored within the ECASD and can be
+     * retrieved by the Device at any time using the standard GlobalPlatform GET DATA command.
+     *
+     * This data is mandatory and applicable only when cardState is CardStatus.STATE_PRESENT and SIM
+     * card supports eUICC.
+     */
+    String eid;
+    /**
+     * PortInfo contains the ICCID, logical slot ID, and port state.
+     * Cardstate has no relationship with whether the slot is active or inactive. Should always
+     * report up at least 1 port otherwise the logicalSlotIndex and portActive info will be lost.
+     * For example, the pSIM can be removed, but the slot can still be active. In that case, the
+     * SIM_STATUS reported for the corresponding logical stack will show CARDSTATE_ABSENT.
+     * Similarly, even if there is no profile enabled on the eSIM, that port can still be the
+     * active port in the slot mapping.
+     */
+    SimPortInfo[] portInfo;
+}
diff --git a/radio/aidl/android/hardware/radio/config/SlotPortMapping.aidl b/radio/aidl/android/hardware/radio/config/SlotPortMapping.aidl
new file mode 100644
index 0000000..c78afcb
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/config/SlotPortMapping.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.config;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable SlotPortMapping {
+    /**
+     * Physical slot id is the index of the slots
+     **/
+    int physicalSlotId;
+    /**
+     * PortId is the id (enumerated value) for the associated port available on the SIM.
+     * Example:
+     * if eUICC1 supports 2 ports, then the portId is numbered 0,1.
+     * if eUICC2 supports 4 ports, then the portId is numbered: 0,1,2,3.
+     * Each portId is unique within a UICC, but not necessarily unique across UICC’s.
+     * SEP(Single enabled profile) eUICC and non-eUICC will only have portId 0.
+     **/
+    int portId;
+}
diff --git a/radio/aidl/android/hardware/radio/data/ApnAuthType.aidl b/radio/aidl/android/hardware/radio/data/ApnAuthType.aidl
new file mode 100644
index 0000000..a4116db
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/data/ApnAuthType.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.data;
+
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum ApnAuthType {
+    /**
+     * PAP and CHAP is never performed.
+     */
+    NO_PAP_NO_CHAP,
+    /**
+     * PAP may be performed; CHAP is never performed.
+     */
+    PAP_NO_CHAP,
+    /**
+     * CHAP may be performed; PAP is never performed.
+     */
+    NO_PAP_CHAP,
+    /**
+     * PAP / CHAP may be performed - baseband dependent.
+     */
+    PAP_CHAP,
+}
diff --git a/radio/aidl/android/hardware/radio/data/ApnTypes.aidl b/radio/aidl/android/hardware/radio/data/ApnTypes.aidl
new file mode 100644
index 0000000..ed1256d
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/data/ApnTypes.aidl
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.data;
+
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum ApnTypes {
+    /**
+     * None
+     */
+    NONE = 0,
+    /**
+     * APN type for default data traffic
+     */
+    DEFAULT = 1 << 0,
+    /**
+     * APN type for MMS traffic
+     */
+    MMS = 1 << 1,
+    /**
+     * APN type for SUPL assisted GPS
+     */
+    SUPL = 1 << 2,
+    /**
+     * APN type for DUN traffic
+     */
+    DUN = 1 << 3,
+    /**
+     * APN type for HiPri traffic
+     */
+    HIPRI = 1 << 4,
+    /**
+     * APN type for FOTA
+     */
+    FOTA = 1 << 5,
+    /**
+     * APN type for IMS
+     */
+    IMS = 1 << 6,
+    /**
+     * APN type for CBS
+     */
+    CBS = 1 << 7,
+    /**
+     * APN type for IA Initial Attach APN
+     */
+    IA = 1 << 8,
+    /**
+     * APN type for Emergency PDN. This is not an IA apn, but is used for access to carrier services
+     * in an emergency call situation.
+     */
+    EMERGENCY = 1 << 9,
+    /**
+     * APN type for Mission Critical Service
+     * Reference: 3GPP TS 22.280 V15.3.0
+     */
+    MCX = 1 << 10,
+    /**
+     * APN type for XCAP
+     */
+    XCAP = 1 << 11,
+    /**
+     * APN type for VSIM.
+     */
+    VSIM = 1 << 12,
+    /**
+     * APN type for BIP.
+     */
+    BIP = 1 << 13,
+    /**
+     * APN type for ENTERPRISE
+     */
+    ENTERPRISE = 1 << 14
+}
diff --git a/radio/aidl/android/hardware/radio/data/DataCallFailCause.aidl b/radio/aidl/android/hardware/radio/data/DataCallFailCause.aidl
new file mode 100644
index 0000000..29ece76
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/data/DataCallFailCause.aidl
@@ -0,0 +1,1304 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.data;
+
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum DataCallFailCause {
+    /**
+     * An integer cause code defined in TS 24.008 section 6.1.3.1.3 or TS 24.301 Release 8+ Annex B.
+     * If the implementation does not have access to the exact cause codes, then it must return one
+     * of the following values, as the UI layer needs to distinguish these cases for error
+     * notification and potential retries.
+     */
+    NONE = 0,
+    /**
+     * No retry
+     */
+    OPERATOR_BARRED = 0x08,
+    /**
+     * PDP_FAIL_LLC_SNDCP = 0x19
+     */
+    NAS_SIGNALLING = 0x0E,
+    INSUFFICIENT_RESOURCES = 0x1A,
+    /**
+     * No retry
+     */
+    MISSING_UNKNOWN_APN = 0x1B,
+    /**
+     * No retry
+     */
+    UNKNOWN_PDP_ADDRESS_TYPE = 0x1C,
+    /**
+     * No retry
+     */
+    USER_AUTHENTICATION = 0x1D,
+    /**
+     * No retry
+     */
+    ACTIVATION_REJECT_GGSN = 0x1E,
+    ACTIVATION_REJECT_UNSPECIFIED = 0x1F,
+    /**
+     * No retry
+     */
+    SERVICE_OPTION_NOT_SUPPORTED = 0x20,
+    /**
+     * No retry
+     */
+    SERVICE_OPTION_NOT_SUBSCRIBED = 0x21,
+    SERVICE_OPTION_OUT_OF_ORDER = 0x22,
+    /**
+     * No retry
+     */
+    NSAPI_IN_USE = 0x23,
+    /**
+     * Possibly restart radio, based on framework config
+     */
+    REGULAR_DEACTIVATION = 0x24,
+    QOS_NOT_ACCEPTED = 0x25,
+    NETWORK_FAILURE = 0x26,
+    UMTS_REACTIVATION_REQ = 0x27,
+    FEATURE_NOT_SUPP = 0x28,
+    TFT_SEMANTIC_ERROR = 0x29,
+    TFT_SYTAX_ERROR = 0x2A,
+    UNKNOWN_PDP_CONTEXT = 0x2B,
+    FILTER_SEMANTIC_ERROR = 0x2C,
+    FILTER_SYTAX_ERROR = 0x2D,
+    PDP_WITHOUT_ACTIVE_TFT = 0x2E,
+    /**
+     * No retry
+     */
+    ONLY_IPV4_ALLOWED = 0x32,
+    /**
+     * No retry
+     */
+    ONLY_IPV6_ALLOWED = 0x33,
+    ONLY_SINGLE_BEARER_ALLOWED = 0x34,
+    ESM_INFO_NOT_RECEIVED = 0x35,
+    PDN_CONN_DOES_NOT_EXIST = 0x36,
+    MULTI_CONN_TO_SAME_PDN_NOT_ALLOWED = 0x37,
+    MAX_ACTIVE_PDP_CONTEXT_REACHED = 0x41,
+    UNSUPPORTED_APN_IN_CURRENT_PLMN = 0x42,
+    INVALID_TRANSACTION_ID = 0x51,
+    MESSAGE_INCORRECT_SEMANTIC = 0x5F,
+    INVALID_MANDATORY_INFO = 0x60,
+    MESSAGE_TYPE_UNSUPPORTED = 0x61,
+    MSG_TYPE_NONCOMPATIBLE_STATE = 0x62,
+    UNKNOWN_INFO_ELEMENT = 0x63,
+    CONDITIONAL_IE_ERROR = 0x64,
+    MSG_AND_PROTOCOL_STATE_UNCOMPATIBLE = 0x65,
+    /**
+     * No retry
+     */
+    PROTOCOL_ERRORS = 0x6F,
+    APN_TYPE_CONFLICT = 0x70,
+    INVALID_PCSCF_ADDR = 0x71,
+    INTERNAL_CALL_PREEMPT_BY_HIGH_PRIO_APN = 0x72,
+    EMM_ACCESS_BARRED = 0x73,
+    EMERGENCY_IFACE_ONLY = 0x74,
+    IFACE_MISMATCH = 0x75,
+    COMPANION_IFACE_IN_USE = 0x76,
+    IP_ADDRESS_MISMATCH = 0x77,
+    IFACE_AND_POL_FAMILY_MISMATCH = 0x78,
+    EMM_ACCESS_BARRED_INFINITE_RETRY = 0x79,
+    AUTH_FAILURE_ON_EMERGENCY_CALL = 0x7A,
+    OEM_DCFAILCAUSE_1 = 0x1001,
+    OEM_DCFAILCAUSE_2 = 0x1002,
+    OEM_DCFAILCAUSE_3 = 0x1003,
+    OEM_DCFAILCAUSE_4 = 0x1004,
+    OEM_DCFAILCAUSE_5 = 0x1005,
+    OEM_DCFAILCAUSE_6 = 0x1006,
+    OEM_DCFAILCAUSE_7 = 0x1007,
+    OEM_DCFAILCAUSE_8 = 0x1008,
+    OEM_DCFAILCAUSE_9 = 0x1009,
+    OEM_DCFAILCAUSE_10 = 0x100A,
+    OEM_DCFAILCAUSE_11 = 0x100B,
+    OEM_DCFAILCAUSE_12 = 0x100C,
+    OEM_DCFAILCAUSE_13 = 0x100D,
+    OEM_DCFAILCAUSE_14 = 0x100E,
+    OEM_DCFAILCAUSE_15 = 0x100F,
+    /**
+     * Not mentioned in the specification
+     */
+    VOICE_REGISTRATION_FAIL = -1,
+    /**
+     * Not mentioned in the specification
+     */
+    DATA_REGISTRATION_FAIL = -2,
+    /**
+     * Network/modem disonnect
+     */
+    SIGNAL_LOST = -3,
+    /**
+     * Preferred technology has changed, must retry with parameters appropriate for new technology
+     */
+    PREF_RADIO_TECH_CHANGED = -4,
+    /**
+     * Data call was disconnected because radio was resetting, powered off - no retry
+     */
+    RADIO_POWER_OFF = -5,
+    /**
+     * Data call was disconnected by modem because tethered mode was up on same APN/data profile
+     * No retry until tethered call is off
+     */
+    TETHERED_CALL_ACTIVE = -6,
+    ERROR_UNSPECIFIED = 0xffff,
+    /**
+     * Network cannot provide the requested service and PDP context is deactivated because of LLC
+     * or SNDCP failure.
+     */
+    LLC_SNDCP = 0x19,
+    /**
+     * UE requested to modify QoS parameters or the bearer control mode, which is not compatible
+     * with the selected bearer control mode.
+     */
+    ACTIVATION_REJECTED_BCM_VIOLATION = 0x30,
+    /**
+     * Network has already initiated the activation, modification, or deactivation of bearer
+     * resources that was requested by the UE.
+     */
+    COLLISION_WITH_NETWORK_INITIATED_REQUEST = 0x38,
+    /**
+     * Network supports IPv4v6 PDP type only. Non-IP type is not allowed. In LTE mode of operation,
+     * this is a PDN throttling cause code, meaning the UE may throttle further requests to the
+     * same APN.
+     */
+    ONLY_IPV4V6_ALLOWED = 0x39,
+    /**
+     * Network supports non-IP PDP type only. IPv4, IPv6 and IPv4v6 is not allowed. In LTE mode of
+     * operation, this is a PDN throttling cause code, meaning the UE can throttle further requests
+     * to the same APN.
+     */
+    ONLY_NON_IP_ALLOWED = 0x3A,
+    /**
+     * QCI (QoS Class Identifier) indicated in the UE request cannot be supported.
+     */
+    UNSUPPORTED_QCI_VALUE = 0x3B,
+    /**
+     * Procedure requested by the UE was rejected because the bearer handling is not supported.
+     */
+    BEARER_HANDLING_NOT_SUPPORTED = 0x3C,
+    /**
+     * Not receiving a DNS address that was mandatory.
+     */
+    INVALID_DNS_ADDR = 0x7B,
+    /**
+     * Not receiving either a PCSCF or a DNS address, one of them being mandatory.
+     */
+    INVALID_PCSCF_OR_DNS_ADDRESS = 0x7C,
+    /**
+     * Emergency call bring up on a different ePDG.
+     */
+    CALL_PREEMPT_BY_EMERGENCY_APN = 0x7F,
+    /**
+     * UE performs a detach or disconnect PDN action based on TE requirements.
+     */
+    UE_INITIATED_DETACH_OR_DISCONNECT = 0x80,
+    /**
+     * Reason unspecified for foreign agent rejected MIP (Mobile IP) registration.
+     */
+    MIP_FA_REASON_UNSPECIFIED = 0x7D0,
+    /**
+     * Foreign agent administratively prohibited MIP (Mobile IP) registration.
+     */
+    MIP_FA_ADMIN_PROHIBITED = 0x7D1,
+    /**
+     * Foreign agent rejected MIP (Mobile IP) registration because of insufficient resources.
+     */
+    MIP_FA_INSUFFICIENT_RESOURCES = 0x7D2,
+    /**
+     * Foreign agent rejected MIP (Mobile IP) registration because of MN-AAA authenticator was
+     * wrong.
+     */
+    MIP_FA_MOBILE_NODE_AUTHENTICATION_FAILURE = 0x7D3,
+    /**
+     * Foreign agent rejected MIP (Mobile IP) registration because of home agent authentication
+     * failure.
+     */
+    MIP_FA_HOME_AGENT_AUTHENTICATION_FAILURE = 0x7D4,
+    /**
+     * Foreign agent rejected MIP (Mobile IP) registration because of requested lifetime was too
+     * long.
+     */
+    MIP_FA_REQUESTED_LIFETIME_TOO_LONG = 0x7D5,
+    /**
+     * Foreign agent rejected MIP (Mobile IP) registration because of malformed request.
+     */
+    MIP_FA_MALFORMED_REQUEST = 0x7D6,
+    /**
+     * Foreign agent rejected MIP (Mobile IP) registration because of malformed reply.
+     */
+    MIP_FA_MALFORMED_REPLY = 0x7D7,
+    /**
+     * Foreign agent rejected MIP (Mobile IP) registration because of requested encapsulation was
+     * unavailable.
+     */
+    MIP_FA_ENCAPSULATION_UNAVAILABLE = 0x7D8,
+    /**
+     * Foreign agent rejected MIP (Mobile IP) registration of VJ Header Compression was unavailable.
+     */
+    MIP_FA_VJ_HEADER_COMPRESSION_UNAVAILABLE = 0x7D9,
+    /**
+     * Foreign agent rejected MIP (Mobile IP) registration because of reverse tunnel was
+     * unavailable.
+     */
+    MIP_FA_REVERSE_TUNNEL_UNAVAILABLE = 0x7DA,
+    /**
+     * Foreign agent rejected MIP (Mobile IP) registration because of reverse tunnel was mandatory
+     * but not requested by device.
+     */
+    MIP_FA_REVERSE_TUNNEL_IS_MANDATORY = 0x7DB,
+    /**
+     * Foreign agent rejected MIP (Mobile IP) registration because of delivery style was not
+     * supported.
+     */
+    MIP_FA_DELIVERY_STYLE_NOT_SUPPORTED = 0x7DC,
+    /**
+     * Foreign agent rejected MIP (Mobile IP) registration because of missing NAI (Network Access
+     * Identifier).
+     */
+    MIP_FA_MISSING_NAI = 0x7DD,
+    /**
+     * Foreign agent rejected MIP (Mobile IP) registration because of missing Home Agent.
+     */
+    MIP_FA_MISSING_HOME_AGENT = 0x7DE,
+    /**
+     * Foreign agent rejected MIP (Mobile IP) registration because of missing Home Address.
+     */
+    MIP_FA_MISSING_HOME_ADDRESS = 0x7DF,
+    /**
+     * Foreign agent rejected MIP (Mobile IP) registration because of unknown challenge.
+     */
+    MIP_FA_UNKNOWN_CHALLENGE = 0x7E0,
+    /**
+     * Foreign agent rejected MIP (Mobile IP) registration because of missing challenge.
+     */
+    MIP_FA_MISSING_CHALLENGE = 0x7E1,
+    /**
+     * Foreign agent rejected MIP (Mobile IP) registration because of stale challenge.
+     */
+    MIP_FA_STALE_CHALLENGE = 0x7E2,
+    /**
+     * Reason unspecified for home agent rejected MIP (Mobile IP) registration.
+     */
+    MIP_HA_REASON_UNSPECIFIED = 0x7E3,
+    /**
+     * Home agent administratively prohibited MIP (Mobile IP) registration.
+     */
+    MIP_HA_ADMIN_PROHIBITED = 0x7E4,
+    /**
+     * Home agent rejected MIP (Mobile IP) registration because of insufficient resources.
+     */
+    MIP_HA_INSUFFICIENT_RESOURCES = 0x7E5,
+    /**
+     * Home agent rejected MIP (Mobile IP) registration because of MN-HA authenticator was wrong.
+     */
+    MIP_HA_MOBILE_NODE_AUTHENTICATION_FAILURE = 0x7E6,
+    /**
+     * Home agent rejected MIP (Mobile IP) registration because of foreign agent authentication
+     * failure.
+     */
+    MIP_HA_FOREIGN_AGENT_AUTHENTICATION_FAILURE = 0x7E7,
+    /**
+     * Home agent rejected MIP (Mobile IP) registration because of registration id mismatch.
+     */
+    MIP_HA_REGISTRATION_ID_MISMATCH = 0x7E8,
+    /**
+     * Home agent rejected MIP (Mobile IP) registration because of malformed request.
+     */
+    MIP_HA_MALFORMED_REQUEST = 0x7E9,
+    /**
+     * Home agent rejected MIP (Mobile IP) registration because of unknown home agent address.
+     */
+    MIP_HA_UNKNOWN_HOME_AGENT_ADDRESS = 0x7EA,
+    /**
+     * Home agent rejected MIP (Mobile IP) registration because of reverse tunnel was unavailable.
+     */
+    MIP_HA_REVERSE_TUNNEL_UNAVAILABLE = 0x7EB,
+    /**
+     * Home agent rejected MIP (Mobile IP) registration because of reverse tunnel is mandatory but
+     * not requested by device.
+     */
+    MIP_HA_REVERSE_TUNNEL_IS_MANDATORY = 0x7EC,
+    /**
+     * Home agent rejected MIP (Mobile IP) registration because of encapsulation unavailable.
+     */
+    MIP_HA_ENCAPSULATION_UNAVAILABLE = 0x7ED,
+    /**
+     * Tearing down is in progress.
+     */
+    CLOSE_IN_PROGRESS = 0x7EE,
+    /**
+     * Brought down by the network.
+     */
+    NETWORK_INITIATED_TERMINATION = 0x7EF,
+    /**
+     * Another application in modem preempts the data call.
+     */
+    MODEM_APP_PREEMPTED = 0x7F0,
+    /**
+     * IPV4 PDN is in throttled state due to network providing only IPV6 address during the previous
+     * VSNCP bringup (subs_limited_to_v6).
+     */
+    PDN_IPV4_CALL_DISALLOWED = 0x7F1,
+    /**
+     * IPV4 PDN is in throttled state due to previous VSNCP bringup failure(s).
+     */
+    PDN_IPV4_CALL_THROTTLED = 0x7F2,
+    /**
+     * IPV6 PDN is in throttled state due to network providing only IPV4 address during the previous
+     * VSNCP bringup (subs_limited_to_v4).
+     */
+    PDN_IPV6_CALL_DISALLOWED = 0x7F3,
+    /**
+     * IPV6 PDN is in throttled state due to previous VSNCP bringup failure(s).
+     */
+    PDN_IPV6_CALL_THROTTLED = 0x7F4,
+    /**
+     * Modem restart.
+     */
+    MODEM_RESTART = 0x7F5,
+    /**
+     * PDP PPP calls are not supported.
+     */
+    PDP_PPP_NOT_SUPPORTED = 0x7F6,
+    /**
+     * RAT on which the data call is attempted/connected is no longer the preferred RAT.
+     */
+    UNPREFERRED_RAT = 0x7F7,
+    /**
+     * Physical link is in the process of cleanup.
+     */
+    PHYSICAL_LINK_CLOSE_IN_PROGRESS = 0x7F8,
+    /**
+     * Interface bring up is attempted for an APN that is yet to be handed over to target RAT.
+     */
+    APN_PENDING_HANDOVER = 0x7F9,
+    /**
+     * APN bearer type in the profile does not match preferred network mode.
+     */
+    PROFILE_BEARER_INCOMPATIBLE = 0x7FA,
+    /**
+     * Card was refreshed or removed.
+     */
+    SIM_CARD_CHANGED = 0x7FB,
+    /**
+     * Device is going into lower power mode or powering down.
+     */
+    LOW_POWER_MODE_OR_POWERING_DOWN = 0x7FC,
+    /**
+     * APN has been disabled.
+     */
+    APN_DISABLED = 0x7FD,
+    /**
+     * Maximum PPP inactivity timer expired.
+     */
+    MAX_PPP_INACTIVITY_TIMER_EXPIRED = 0x7FE,
+    /**
+     * IPv6 address transfer failed.
+     */
+    IPV6_ADDRESS_TRANSFER_FAILED = 0x7FF,
+    /**
+     * Target RAT swap failed.
+     */
+    TRAT_SWAP_FAILED = 0x800,
+    /**
+     * Device falls back from eHRPD to HRPD.
+     */
+    EHRPD_TO_HRPD_FALLBACK = 0x801,
+    /**
+     * UE is in MIP-only configuration but the MIP configuration fails on call bring up due to
+     * incorrect provisioning.
+     */
+    MIP_CONFIG_FAILURE = 0x802,
+    /**
+     * PDN inactivity timer expired due to no data transmission in a configurable duration of time.
+     */
+    PDN_INACTIVITY_TIMER_EXPIRED = 0x803,
+    /**
+     * IPv4 data call bring up is rejected because the UE already maintains the allotted maximum
+     * number of IPv4 data connections.
+     */
+    MAX_IPV4_CONNECTIONS = 0x804,
+    /**
+     * IPv6 data call bring up is rejected because the UE already maintains the allotted maximum
+     * number of IPv6 data connections.
+     */
+    MAX_IPV6_CONNECTIONS = 0x805,
+    /**
+     * New PDN bring up is rejected during interface selection because the UE has already allotted
+     * the available interfaces for other PDNs.
+     */
+    APN_MISMATCH = 0x806,
+    /**
+     * New call bring up is rejected since the existing data call IP type doesn't match the
+     * requested IP.
+     */
+    IP_VERSION_MISMATCH = 0x807,
+    /**
+     * Dial up networking (DUN) call bring up is rejected since UE is in eHRPD RAT.
+     */
+    DUN_CALL_DISALLOWED = 0x808,
+    /**
+     * Rejected/Brought down since UE is transition between EPC and NONEPC RAT.
+     */
+    INTERNAL_EPC_NONEPC_TRANSITION = 0x809,
+    /**
+     * The current interface is being in use.
+     */
+    INTERFACE_IN_USE = 0x80A,
+    /**
+     * PDN connection to the APN is disallowed on the roaming network.
+     */
+    APN_DISALLOWED_ON_ROAMING = 0x80B,
+    /**
+     * APN-related parameters are changed.
+     */
+    APN_PARAMETERS_CHANGED = 0x80C,
+    /**
+     * PDN is attempted to be brought up with NULL APN but NULL APN is not supported.
+     */
+    NULL_APN_DISALLOWED = 0x80D,
+    /**
+     * Thermal level increases and causes calls to be torn down when normal mode of operation is
+     * not allowed.
+     */
+    THERMAL_MITIGATION = 0x80E,
+    /**
+     * PDN Connection to a given APN is disallowed because data is disabled from the device user
+     * interface settings.
+     */
+    DATA_SETTINGS_DISABLED = 0x80F,
+    /**
+     * PDN Connection to a given APN is disallowed because data roaming is disabled from the device
+     * user interface settings and the UE is roaming.
+     */
+    DATA_ROAMING_SETTINGS_DISABLED = 0x810,
+    /**
+     * DDS (Default data subscription) switch occurs.
+     */
+    DDS_SWITCHED = 0x811,
+    /**
+     * PDN being brought up with an APN that is part of forbidden APN Name list.
+     */
+    FORBIDDEN_APN_NAME = 0x812,
+    /**
+     * Default data subscription switch is in progress.
+     */
+    DDS_SWITCH_IN_PROGRESS = 0x813,
+    /**
+     * Roaming is disallowed during call bring up.
+     */
+    CALL_DISALLOWED_IN_ROAMING = 0x814,
+    /**
+     * UE is unable to bring up a non-IP data call because the device is not camped on a NB1 cell.
+     */
+    NON_IP_NOT_SUPPORTED = 0x815,
+    /**
+     * Non-IP PDN is in throttled state due to previous VSNCP bringup failure(s).
+     */
+    PDN_NON_IP_CALL_THROTTLED = 0x816,
+    /**
+     * Non-IP PDN is in disallowed state due to the network providing only an IP address.
+     */
+    PDN_NON_IP_CALL_DISALLOWED = 0x817,
+    /**
+     * Device in CDMA locked state.
+     */
+    CDMA_LOCK = 0x818,
+    /**
+     * Received an intercept order from the base station.
+     */
+    CDMA_INTERCEPT = 0x819,
+    /**
+     * Receiving a reorder from the base station.
+     */
+    CDMA_REORDER = 0x81A,
+    /**
+     * Receiving a release from the base station with a SO (Service Option) Reject reason.
+     */
+    CDMA_RELEASE_DUE_TO_SO_REJECTION = 0x81B,
+    /**
+     * Receiving an incoming call from the base station.
+     */
+    CDMA_INCOMING_CALL = 0x81C,
+    /**
+     * Received an alert stop from the base station due to incoming only.
+     */
+    CDMA_ALERT_STOP = 0x81D,
+    /**
+     * Channel acquisition failures. This indicates that device has failed acquiring all the
+     * channels in the PRL.
+     */
+    CHANNEL_ACQUISITION_FAILURE = 0x81E,
+    /**
+     * Maximum access probes transmitted.
+     */
+    MAX_ACCESS_PROBE = 0x81F,
+    /**
+     * Concurrent service is not supported by base station.
+     */
+    CONCURRENT_SERVICE_NOT_SUPPORTED_BY_BASE_STATION = 0x820,
+    /**
+     * There was no response received from the base station.
+     */
+    NO_RESPONSE_FROM_BASE_STATION = 0x821,
+    /**
+     * The base station rejecting the call.
+     */
+    REJECTED_BY_BASE_STATION = 0x822,
+    /**
+     * The concurrent services requested were not compatible.
+     */
+    CONCURRENT_SERVICES_INCOMPATIBLE = 0x823,
+    /**
+     * Device does not have CDMA service.
+     */
+    NO_CDMA_SERVICE = 0x824,
+    /**
+     * RUIM not being present.
+     */
+    RUIM_NOT_PRESENT = 0x825,
+    /**
+     * Receiving a retry order from the base station.
+     */
+    CDMA_RETRY_ORDER = 0x826,
+    /**
+     * Access blocked by the base station.
+     */
+    ACCESS_BLOCK = 0x827,
+    /**
+     * Access blocked by the base station for all mobile devices.
+     */
+    ACCESS_BLOCK_ALL = 0x828,
+    /**
+     * Maximum access probes for the IS-707B call.
+     */
+    IS707B_MAX_ACCESS_PROBES = 0x829,
+    /**
+     * Put device in thermal emergency.
+     */
+    THERMAL_EMERGENCY = 0x82A,
+    /**
+     * In favor of a voice call or SMS when concurrent voice and data are not supported.
+     */
+    CONCURRENT_SERVICES_NOT_ALLOWED = 0x82B,
+    /**
+     * The other clients rejected incoming call.
+     */
+    INCOMING_CALL_REJECTED = 0x82C,
+    /**
+     * No service on the gateway.
+     */
+    NO_SERVICE_ON_GATEWAY = 0x82D,
+    /**
+     * GPRS context is not available.
+     */
+    NO_GPRS_CONTEXT = 0x82E,
+    /**
+     * Network refuses service to the MS because either an identity of the MS is not acceptable to
+     * the network or the MS does not pass the authentication check.
+     */
+    ILLEGAL_MS = 0x82F,
+    /**
+     * ME could not be authenticated and the ME used is not acceptable to the network.
+     */
+    ILLEGAL_ME = 0x830,
+    /**
+     * Not allowed to operate either GPRS or non-GPRS services.
+     */
+    GPRS_SERVICES_AND_NON_GPRS_SERVICES_NOT_ALLOWED = 0x831,
+    /**
+     * MS is not allowed to operate GPRS services.
+     */
+    GPRS_SERVICES_NOT_ALLOWED = 0x832,
+    /**
+     * No matching identity or context could be found in the network.
+     */
+    MS_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK = 0x833,
+    /**
+     * Mobile reachable timer has expired, or the GMM context data related to the subscription does
+     * not exist in the SGSN.
+     */
+    IMPLICITLY_DETACHED = 0x834,
+    /**
+     * UE requests GPRS service, or the network initiates a detach request in a PLMN which does not
+     * offer roaming for GPRS services to that MS.
+     */
+    PLMN_NOT_ALLOWED = 0x835,
+    /**
+     * MS requests service, or the network initiates a detach request, in a location area where the
+     * HPLMN determines that the MS, by subscription, is not allowed to operate.
+     */
+    LOCATION_AREA_NOT_ALLOWED = 0x836,
+    /**
+     * UE requests GPRS service or the network initiates a detach request in a PLMN that does not
+     * offer roaming for GPRS services.
+     */
+    GPRS_SERVICES_NOT_ALLOWED_IN_THIS_PLMN = 0x837,
+    /**
+     * PDP context already exists.
+     */
+    PDP_DUPLICATE = 0x838,
+    /**
+     * RAT change on the UE.
+     */
+    UE_RAT_CHANGE = 0x839,
+    /**
+     * Network cannot serve a request from the MS due to congestion.
+     */
+    CONGESTION = 0x83A,
+    /**
+     * MS requests an establishment of the radio access bearers for all active PDP contexts by
+     * sending a service request message indicating data to the network, but the SGSN does not have
+     * any active PDP context.
+     */
+    NO_PDP_CONTEXT_ACTIVATED = 0x83B,
+    /**
+     * Access class blocking restrictions for the current camped cell.
+     */
+    ACCESS_CLASS_DSAC_REJECTION = 0x83C,
+    /**
+     * SM attempts PDP activation for a maximum of four attempts.
+     */
+    PDP_ACTIVATE_MAX_RETRY_FAILED = 0x83D,
+    /**
+     * Radio access bearer failure.
+     */
+    RADIO_ACCESS_BEARER_FAILURE = 0x83E,
+    /**
+     * Invalid EPS bearer identity in the request.
+     */
+    ESM_UNKNOWN_EPS_BEARER_CONTEXT = 0x83F,
+    /**
+     * Data radio bearer is released by the RRC.
+     */
+    DRB_RELEASED_BY_RRC = 0x840,
+    /**
+     * Indicate the connection was released.
+     */
+    CONNECTION_RELEASED = 0x841,
+    /**
+     * UE is detached.
+     */
+    EMM_DETACHED = 0x842,
+    /**
+     * Attach procedure is rejected by the network.
+     */
+    EMM_ATTACH_FAILED = 0x843,
+    /**
+     * Attach procedure is started for EMC purposes.
+     */
+    EMM_ATTACH_STARTED = 0x844,
+    /**
+     * Service request procedure failure.
+     */
+    LTE_NAS_SERVICE_REQUEST_FAILED = 0x845,
+    /**
+     * Active dedicated bearer was requested using the same default bearer ID.
+     */
+    DUPLICATE_BEARER_ID = 0x846,
+    /**
+     * Collision scenarios for the UE and network-initiated procedures.
+     */
+    ESM_COLLISION_SCENARIOS = 0x847,
+    /**
+     * Bearer must be deactivated to synchronize with the network.
+     */
+    ESM_BEARER_DEACTIVATED_TO_SYNC_WITH_NETWORK = 0x848,
+    /**
+     * Active dedicated bearer was requested for an existing default bearer.
+     */
+    ESM_NW_ACTIVATED_DED_BEARER_WITH_ID_OF_DEF_BEARER = 0x849,
+    /**
+     * Bad OTA message is received from the network.
+     */
+    ESM_BAD_OTA_MESSAGE = 0x84A,
+    /**
+     * Download server rejected the call.
+     */
+    ESM_DOWNLOAD_SERVER_REJECTED_THE_CALL = 0x84B,
+    /**
+     * PDN was disconnected by the downlaod server due to IRAT.
+     */
+    ESM_CONTEXT_TRANSFERRED_DUE_TO_IRAT = 0x84C,
+    /**
+     * Dedicated bearer will be deactivated regardless of the network response.
+     */
+    DS_EXPLICIT_DEACTIVATION = 0x84D,
+    /**
+     * No specific local cause is mentioned, usually a valid OTA cause.
+     */
+    ESM_LOCAL_CAUSE_NONE = 0x84E,
+    /**
+     * Throttling is not needed for this service request failure.
+     */
+    LTE_THROTTLING_NOT_REQUIRED = 0x84F,
+    /**
+     * Access control list check failure at the lower layer.
+     */
+    ACCESS_CONTROL_LIST_CHECK_FAILURE = 0x850,
+    /**
+     * Service is not allowed on the requested PLMN.
+     */
+    SERVICE_NOT_ALLOWED_ON_PLMN = 0x851,
+    /**
+     * T3417 timer expiration of the service request procedure.
+     */
+    EMM_T3417_EXPIRED = 0x852,
+    /**
+     * Extended service request fails due to expiration of the T3417 EXT timer.
+     */
+    EMM_T3417_EXT_EXPIRED = 0x853,
+    /**
+     * Transmission failure of radio resource control (RRC) uplink data.
+     */
+    RRC_UPLINK_DATA_TRANSMISSION_FAILURE = 0x854,
+    /**
+     * Radio resource control (RRC) uplink data delivery failed due to a handover.
+     */
+    RRC_UPLINK_DELIVERY_FAILED_DUE_TO_HANDOVER = 0x855,
+    /**
+     * Radio resource control (RRC) uplink data delivery failed due to a connection release.
+     */
+    RRC_UPLINK_CONNECTION_RELEASE = 0x856,
+    /**
+     * Radio resource control (RRC) uplink data delivery failed due to a radio link failure.
+     */
+    RRC_UPLINK_RADIO_LINK_FAILURE = 0x857,
+    /**
+     * Radio resource control (RRC) is not connected but the non-access stratum (NAS) sends an
+     * uplink data request.
+     */
+    RRC_UPLINK_ERROR_REQUEST_FROM_NAS = 0x858,
+    /**
+     * Radio resource control (RRC) connection failure at access stratum.
+     */
+    RRC_CONNECTION_ACCESS_STRATUM_FAILURE = 0x859,
+    /**
+     * Radio resource control (RRC) connection establishment is aborted due to another procedure.
+     */
+    RRC_CONNECTION_ANOTHER_PROCEDURE_IN_PROGRESS = 0x85A,
+    /**
+     * Radio resource control (RRC) connection establishment failed due to access barrred.
+     */
+    RRC_CONNECTION_ACCESS_BARRED = 0x85B,
+    /**
+     * Radio resource control (RRC) connection establishment failed due to cell reselection at
+     * access stratum.
+     */
+    RRC_CONNECTION_CELL_RESELECTION = 0x85C,
+    /**
+     * Connection establishment failed due to configuration failure at the radio resource control
+     * (RRC).
+     */
+    RRC_CONNECTION_CONFIG_FAILURE = 0x85D,
+    /**
+     * Radio resource control (RRC) connection could not be established in the time limit.
+     */
+    RRC_CONNECTION_TIMER_EXPIRED = 0x85E,
+    /**
+     * Connection establishment failed due to a link failure at the radio resource control (RRC).
+     */
+    RRC_CONNECTION_LINK_FAILURE = 0x85F,
+    /**
+     * Connection establishment failed as the radio resource control (RRC) is not camped on any
+     * cell.
+     */
+    RRC_CONNECTION_CELL_NOT_CAMPED = 0x860,
+    /**
+     * Connection establishment failed due to a service interval failure at the radio resource
+     * control (RRC).
+     */
+    RRC_CONNECTION_SYSTEM_INTERVAL_FAILURE = 0x861,
+    /**
+     * Radio resource control (RRC) connection establishment failed due to the network rejecting the
+     * UE connection request.
+     */
+    RRC_CONNECTION_REJECT_BY_NETWORK = 0x862,
+    /**
+     * Normal radio resource control (RRC) connection release.
+     */
+    RRC_CONNECTION_NORMAL_RELEASE = 0x863,
+    /**
+     * Radio resource control (RRC) connection release failed due to radio link failure conditions.
+     */
+    RRC_CONNECTION_RADIO_LINK_FAILURE = 0x864,
+    /**
+     * Radio resource control (RRC) connection re-establishment failure.
+     */
+    RRC_CONNECTION_REESTABLISHMENT_FAILURE = 0x865,
+    /**
+     * UE is out of service during the call register.
+     */
+    RRC_CONNECTION_OUT_OF_SERVICE_DURING_CELL_REGISTER = 0x866,
+    /**
+     * Connection has been released by the radio resource control (RRC) due to an abort request.
+     */
+    RRC_CONNECTION_ABORT_REQUEST = 0x867,
+    /**
+     * Radio resource control (RRC) connection released due to a system information block read
+     * error.
+     */
+    RRC_CONNECTION_SYSTEM_INFORMATION_BLOCK_READ_ERROR = 0x868,
+    /**
+     * Network-initiated detach with reattach.
+     */
+    NETWORK_INITIATED_DETACH_WITH_AUTO_REATTACH = 0x869,
+    /**
+     * Network-initiated detach without reattach.
+     */
+    NETWORK_INITIATED_DETACH_NO_AUTO_REATTACH = 0x86A,
+    /**
+     * ESM procedure maximum attempt timeout failure.
+     */
+    ESM_PROCEDURE_TIME_OUT = 0x86B,
+    /**
+     * No PDP exists with the given connection ID while modifying or deactivating or activation for
+     * an already active PDP.
+     */
+    INVALID_CONNECTION_ID = 0x86C,
+    /**
+     * Maximum NSAPIs have been exceeded during PDP activation.
+     */
+    MAXIMIUM_NSAPIS_EXCEEDED = 0x86D,
+    /**
+     * Primary context for NSAPI does not exist.
+     */
+    INVALID_PRIMARY_NSAPI = 0x86E,
+    /**
+     * Unable to encode the OTA message for MT PDP or deactivate PDP.
+     */
+    CANNOT_ENCODE_OTA_MESSAGE = 0x86F,
+    /**
+     * Radio access bearer is not established by the lower layers during activation, modification,
+     * or deactivation.
+     */
+    RADIO_ACCESS_BEARER_SETUP_FAILURE = 0x870,
+    /**
+     * Expiration of the PDP establish timer with a maximum of five retries.
+     */
+    PDP_ESTABLISH_TIMEOUT_EXPIRED = 0x871,
+    /**
+     * Expiration of the PDP modify timer with a maximum of four retries.
+     */
+    PDP_MODIFY_TIMEOUT_EXPIRED = 0x872,
+    /**
+     * Expiration of the PDP deactivate timer with a maximum of four retries.
+     */
+    PDP_INACTIVE_TIMEOUT_EXPIRED = 0x873,
+    /**
+     * PDP activation failed due to RRC_ABORT or a forbidden PLMN.
+     */
+    PDP_LOWERLAYER_ERROR = 0x874,
+    /**
+     * MO PDP modify collision when the MT PDP is already in progress.
+     */
+    PDP_MODIFY_COLLISION = 0x875,
+    /**
+     * Maximum size of the L2 message was exceeded.
+     */
+    MAXINUM_SIZE_OF_L2_MESSAGE_EXCEEDED = 0x876,
+    /**
+     * Non-access stratum (NAS) request was rejected by the network.
+     */
+    NAS_REQUEST_REJECTED_BY_NETWORK = 0x877,
+    /**
+     * Radio resource control (RRC) connection establishment failure due to an error in the request
+     * message.
+     */
+    RRC_CONNECTION_INVALID_REQUEST = 0x878,
+    /**
+     * Radio resource control (RRC) connection establishment failure due to a change in the tracking
+     * area ID.
+     */
+    RRC_CONNECTION_TRACKING_AREA_ID_CHANGED = 0x879,
+    /**
+     * Radio resource control (RRC) connection establishment failure due to the RF was unavailable.
+     */
+    RRC_CONNECTION_RF_UNAVAILABLE = 0x87A,
+    /**
+     * Radio resource control (RRC) connection was aborted before deactivating the LTE stack due to
+     * a successful LTE to WCDMA/GSM/TD-SCDMA IRAT change.
+     */
+    RRC_CONNECTION_ABORTED_DUE_TO_IRAT_CHANGE = 0x87B,
+    /**
+     * If the UE has an LTE radio link failure before security is established, the radio resource
+     * control (RRC) connection must be released and the UE must return to idle.
+     */
+    RRC_CONNECTION_RELEASED_SECURITY_NOT_ACTIVE = 0x87C,
+    /**
+     * Radio resource control (RRC) connection was aborted by the non-access stratum (NAS) after an
+     * IRAT to LTE IRAT handover.
+     */
+    RRC_CONNECTION_ABORTED_AFTER_HANDOVER = 0x87D,
+    /**
+     * Radio resource control (RRC) connection was aborted before deactivating the LTE stack after a
+     * successful LTE to GSM/EDGE IRAT cell change order procedure.
+     */
+    RRC_CONNECTION_ABORTED_AFTER_IRAT_CELL_CHANGE = 0x87E,
+    /**
+     * Radio resource control (RRC) connection was aborted in the middle of a LTE to GSM IRAT cell
+     * change order procedure.
+     */
+    RRC_CONNECTION_ABORTED_DURING_IRAT_CELL_CHANGE = 0x87F,
+    /**
+     * IMSI present in the UE is unknown in the home subscriber server.
+     */
+    IMSI_UNKNOWN_IN_HOME_SUBSCRIBER_SERVER = 0x880,
+    /**
+     * IMEI of the UE is not accepted by the network.
+     */
+    IMEI_NOT_ACCEPTED = 0x881,
+    /**
+     * EPS and non-EPS services are not allowed by the network.
+     */
+    EPS_SERVICES_AND_NON_EPS_SERVICES_NOT_ALLOWED = 0x882,
+    /**
+     * EPS services are not allowed in the PLMN.
+     */
+    EPS_SERVICES_NOT_ALLOWED_IN_PLMN = 0x883,
+    /**
+     * Mobile switching center is temporarily unreachable.
+     */
+    MSC_TEMPORARILY_NOT_REACHABLE = 0x884,
+    /**
+     * CS domain is not available.
+     */
+    CS_DOMAIN_NOT_AVAILABLE = 0x885,
+    /**
+     * ESM level failure.
+     */
+    ESM_FAILURE = 0x886,
+    /**
+     * MAC level failure.
+     */
+    MAC_FAILURE = 0x887,
+    /**
+     * Synchronization failure.
+     */
+    SYNCHRONIZATION_FAILURE = 0x888,
+    /**
+     * UE security capabilities mismatch.
+     */
+    UE_SECURITY_CAPABILITIES_MISMATCH = 0x889,
+    /**
+     * Unspecified security mode reject.
+     */
+    SECURITY_MODE_REJECTED = 0x88A,
+    /**
+     * Unacceptable non-EPS authentication.
+     */
+    UNACCEPTABLE_NON_EPS_AUTHENTICATION = 0x88B,
+    /**
+     * CS fallback call establishment is not allowed.
+     */
+    CS_FALLBACK_CALL_ESTABLISHMENT_NOT_ALLOWED = 0x88C,
+    /**
+     * No EPS bearer context was activated.
+     */
+    NO_EPS_BEARER_CONTEXT_ACTIVATED = 0x88D,
+    /**
+     * Invalid EMM state.
+     */
+    INVALID_EMM_STATE = 0x88E,
+    /**
+     * Non-Access Spectrum layer failure.
+     */
+    NAS_LAYER_FAILURE = 0x88F,
+    /**
+     * Multiple PDP call feature is disabled.
+     */
+    MULTIPLE_PDP_CALL_NOT_ALLOWED = 0x890,
+    /**
+     * Data call has been brought down because EMBMS is not enabled at the RRC layer.
+     */
+    EMBMS_NOT_ENABLED = 0x891,
+    /**
+     * Data call was unsuccessfully transferred during the IRAT handover.
+     */
+    IRAT_HANDOVER_FAILED = 0x892,
+    /**
+     * EMBMS data call has been successfully brought down.
+     */
+    EMBMS_REGULAR_DEACTIVATION = 0x893,
+    /**
+     * Test loop-back data call has been successfully brought down.
+     */
+    TEST_LOOPBACK_REGULAR_DEACTIVATION = 0x894,
+    /**
+     * Lower layer registration failure.
+     */
+    LOWER_LAYER_REGISTRATION_FAILURE = 0x895,
+    /**
+     * Network initiates a detach on LTE with error cause "data plan has been replenished or has
+     * expired".
+     */
+    DATA_PLAN_EXPIRED = 0x896,
+    /**
+     * UMTS interface is brought down due to handover from UMTS to iWLAN.
+     */
+    UMTS_HANDOVER_TO_IWLAN = 0x897,
+    /**
+     * Received a connection deny due to general or network busy on EVDO network.
+     */
+    EVDO_CONNECTION_DENY_BY_GENERAL_OR_NETWORK_BUSY = 0x898,
+    /**
+     * Received a connection deny due to billing or authentication failure on EVDO network.
+     */
+    EVDO_CONNECTION_DENY_BY_BILLING_OR_AUTHENTICATION_FAILURE = 0x899,
+    /**
+     * HDR system has been changed due to redirection or the PRL was not preferred.
+     */
+    EVDO_HDR_CHANGED = 0x89A,
+    /**
+     * Device exited HDR due to redirection or the PRL was not preferred.
+     */
+    EVDO_HDR_EXITED = 0x89B,
+    /**
+     * Device does not have an HDR session.
+     */
+    EVDO_HDR_NO_SESSION = 0x89C,
+    /**
+     * It is ending an HDR call origination in favor of a GPS fix.
+     */
+    EVDO_USING_GPS_FIX_INSTEAD_OF_HDR_CALL = 0x89D,
+    /**
+     * Connection setup on the HDR system was time out.
+     */
+    EVDO_HDR_CONNECTION_SETUP_TIMEOUT = 0x89E,
+    /**
+     * Device failed to acquire a co-located HDR for origination.
+     */
+    FAILED_TO_ACQUIRE_COLOCATED_HDR = 0x89F,
+    /**
+     * OTASP commit is in progress.
+     */
+    OTASP_COMMIT_IN_PROGRESS = 0x8A0,
+    /**
+     * Device has no hybrid HDR service.
+     */
+    NO_HYBRID_HDR_SERVICE = 0x8A1,
+    /**
+     * HDR module could not be obtained because of the RF locked.
+     */
+    HDR_NO_LOCK_GRANTED = 0x8A2,
+    /**
+     * DBM or SMS is in progress.
+     */
+    DBM_OR_SMS_IN_PROGRESS = 0x8A3,
+    /**
+     * HDR module released the call due to fade.
+     */
+    HDR_FADE = 0x8A4,
+    /**
+     * HDR system access failure.
+     */
+    HDR_ACCESS_FAILURE = 0x8A5,
+    /**
+     * P_rev supported by 1 base station is less than 6, which is not supported for a 1X data call.
+     * The UE must be in the footprint of BS which has p_rev >= 6 to support this SO33 call.
+     */
+    UNSUPPORTED_1X_PREV = 0x8A6,
+    /**
+     * Client ended the data call.
+     */
+    LOCAL_END = 0x8A7,
+    /**
+     * Device has no service.
+     */
+    NO_SERVICE = 0x8A8,
+    /**
+     * Device lost the system due to fade.
+     */
+    FADE = 0x8A9,
+    /**
+     * Receiving a release from the base station with no reason.
+     */
+    NORMAL_RELEASE = 0x8AA,
+    /**
+     * Access attempt is already in progress.
+     */
+    ACCESS_ATTEMPT_ALREADY_IN_PROGRESS = 0x8AB,
+    /**
+     * Device is in the process of redirecting or handing off to a different target system.
+     */
+    REDIRECTION_OR_HANDOFF_IN_PROGRESS = 0x8AC,
+    /**
+     * Device is operating in Emergency mode.
+     */
+    EMERGENCY_MODE = 0x8AD,
+    /**
+     * Device is in use (e.g., voice call).
+     */
+    PHONE_IN_USE = 0x8AE,
+    /**
+     * Device operational mode is different from the mode requested in the traffic channel bring up.
+     */
+    INVALID_MODE = 0x8AF,
+    /**
+     * SIM was marked by the network as invalid for the circuit and/or packet service domain.
+     */
+    INVALID_SIM_STATE = 0x8B0,
+    /**
+     * There is no co-located HDR.
+     */
+    NO_COLLOCATED_HDR = 0x8B1,
+    /**
+     * UE is entering power save mode.
+     */
+    UE_IS_ENTERING_POWERSAVE_MODE = 0x8B2,
+    /**
+     * Dual switch from single standby to dual standby is in progress.
+     */
+    DUAL_SWITCH = 0x8B3,
+    /**
+     * Data call bring up fails in the PPP setup due to a timeout. (e.g., an LCP conf ack was not
+     * received from the network)
+     */
+    PPP_TIMEOUT = 0x8B4,
+    /**
+     * Data call bring up fails in the PPP setup due to an authorization failure.
+     * (e.g., authorization is required, but not negotiated with the network during an LCP phase)
+     */
+    PPP_AUTH_FAILURE = 0x8B5,
+    /**
+     * Data call bring up fails in the PPP setup due to an option mismatch.
+     */
+    PPP_OPTION_MISMATCH = 0x8B6,
+    /**
+     * Data call bring up fails in the PPP setup due to a PAP failure.
+     */
+    PPP_PAP_FAILURE = 0x8B7,
+    /**
+     * Data call bring up fails in the PPP setup due to a CHAP failure.
+     */
+    PPP_CHAP_FAILURE = 0x8B8,
+    /**
+     * Data call bring up fails in the PPP setup because the PPP is in the process of cleaning the
+     * previous PPP session.
+     */
+    PPP_CLOSE_IN_PROGRESS = 0x8B9,
+    /**
+     * IPv6 interface bring up fails because the network provided only the IPv4 address for the
+     * upcoming PDN permanent client can reattempt a IPv6 call bring up after the IPv4 interface is
+     * also brought down. However, there is no guarantee that the network will provide a IPv6
+     * address.
+     */
+    LIMITED_TO_IPV4 = 0x8BA,
+    /**
+     * IPv4 interface bring up fails because the network provided only the IPv6 address for the
+     * upcoming PDN permanent client can reattempt a IPv4 call bring up after the IPv6 interface is
+     * also brought down. However there is no guarantee that the network will provide a IPv4
+     * address.
+     */
+    LIMITED_TO_IPV6 = 0x8BB,
+    /**
+     * Data call bring up fails in the VSNCP phase due to a VSNCP timeout error.
+     */
+    VSNCP_TIMEOUT = 0x8BC,
+    /**
+     * Data call bring up fails in the VSNCP phase due to a general error. It's used when there is
+     * no other specific error code available to report the failure.
+     */
+    VSNCP_GEN_ERROR = 0x8BD,
+    /**
+     * Data call bring up fails in the VSNCP phase due to a network rejection of the VSNCP
+     * configuration request because the requested APN is unauthorized.
+     */
+    VSNCP_APN_UNAUTHORIZED = 0x8BE,
+    /**
+     * Data call bring up fails in the VSNCP phase due to a network rejection of the VSNCP
+     * configuration request because the PDN limit has been exceeded.
+     */
+    VSNCP_PDN_LIMIT_EXCEEDED = 0x8BF,
+    /**
+     * Data call bring up fails in the VSNCP phase due to the network rejected the VSNCP
+     * configuration request due to no PDN gateway address.
+     */
+    VSNCP_NO_PDN_GATEWAY_ADDRESS = 0x8C0,
+    /**
+     * Data call bring up fails in the VSNCP phase due to a network rejection of the VSNCP
+     * configuration request because the PDN gateway is unreachable.
+     */
+    VSNCP_PDN_GATEWAY_UNREACHABLE = 0x8C1,
+    /**
+     * Data call bring up fails in the VSNCP phase due to a network rejection of the VSNCP
+     * configuration request due to a PDN gateway reject.
+     */
+    VSNCP_PDN_GATEWAY_REJECT = 0x8C2,
+    /**
+     * Data call bring up fails in the VSNCP phase due to a network rejection of the VSNCP
+     * configuration request with the reason of insufficient parameter.
+     */
+    VSNCP_INSUFFICIENT_PARAMETERS = 0x8C3,
+    /**
+     * Data call bring up fails in the VSNCP phase due to a network rejection of the VSNCP
+     * configuration request with the reason of resource unavailable.
+     */
+    VSNCP_RESOURCE_UNAVAILABLE = 0x8C4,
+    /**
+     * Data call bring up fails in the VSNCP phase due to a network rejection of the VSNCP
+     * configuration request with the reason of administratively prohibited at the HSGW.
+     */
+    VSNCP_ADMINISTRATIVELY_PROHIBITED = 0x8C5,
+    /**
+     * Data call bring up fails in the VSNCP phase due to a network rejection of PDN ID in use, or
+     * all existing PDNs are brought down with this end reason because one of the PDN bring up was
+     * rejected by the network with the reason of PDN ID in use.
+     */
+    VSNCP_PDN_ID_IN_USE = 0x8C6,
+    /**
+     * Data call bring up fails in the VSNCP phase due to a network rejection of the VSNCP
+     * configuration request for the reason of subscriber limitation.
+     */
+    VSNCP_SUBSCRIBER_LIMITATION = 0x8C7,
+    /**
+     * Data call bring up fails in the VSNCP phase due to a network rejection of the VSNCP
+     * configuration request because the PDN exists for this APN.
+     */
+    VSNCP_PDN_EXISTS_FOR_THIS_APN = 0x8C8,
+    /**
+     * Data call bring up fails in the VSNCP phase due to a network rejection of the VSNCP
+     * configuration request with reconnect to this PDN not allowed, or an active data call is
+     * terminated by the network because reconnection to this PDN is not allowed. Upon receiving
+     * this error code from the network, the modem infinitely throttles the PDN until the next power
+     * cycle.
+     */
+    VSNCP_RECONNECT_NOT_ALLOWED = 0x8C9,
+    /**
+     * Device failure to obtain the prefix from the network.
+     */
+    IPV6_PREFIX_UNAVAILABLE = 0x8CA,
+    /**
+     * System preference change back to SRAT during handoff
+     */
+    HANDOFF_PREFERENCE_CHANGED = 0x8CB,
+    /**
+     * Data call fail due to the slice not being allowed for the data call.
+     */
+    SLICE_REJECTED = 0x8CC,
+    /**
+     * No matching rule available for the request, and match-all rule is not allowed for it.
+     */
+    MATCH_ALL_RULE_NOT_ALLOWED = 0x8CD,
+    /**
+     * If connection failed for all matching URSP rules.
+     */
+    ALL_MATCHING_RULES_FAILED = 0x8CE,
+}
diff --git a/radio/aidl/android/hardware/radio/data/DataProfileInfo.aidl b/radio/aidl/android/hardware/radio/data/DataProfileInfo.aidl
new file mode 100644
index 0000000..ea4e751
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/data/DataProfileInfo.aidl
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.data;
+
+import android.hardware.radio.data.ApnAuthType;
+import android.hardware.radio.data.PdpProtocolType;
+import android.hardware.radio.data.TrafficDescriptor;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable DataProfileInfo {
+    const int ID_DEFAULT = 0;
+    const int ID_TETHERED = 1;
+    const int ID_IMS = 2;
+    const int ID_FOTA = 3;
+    const int ID_CBS = 4;
+    /**
+     * Start of OEM-specific profiles
+     */
+    const int ID_OEM_BASE = 1000;
+    const int ID_INVALID = 0xFFFFFFFF;
+
+    const int TYPE_COMMON = 0;
+    const int TYPE_3GPP = 1;
+    const int TYPE_3GPP2 = 2;
+
+    /**
+     * ID of the data profile.
+     * Values are ID_
+     */
+    int profileId;
+    /**
+     * The APN name.
+     */
+    String apn;
+    /**
+     * PDP_type values.
+     */
+    PdpProtocolType protocol;
+    /**
+     * PDP_type values used on roaming network.
+     */
+    PdpProtocolType roamingProtocol;
+    /**
+     * APN authentication type.
+     */
+    ApnAuthType authType;
+    /**
+     * The username for APN, or empty string.
+     */
+    String user;
+    /**
+     * The password for APN, or empty string.
+     */
+    String password;
+    /**
+     * Data profile technology type.
+     * Values are TYPE_
+     */
+    int type;
+    /**
+     * The period in seconds to limit the maximum connections.
+     */
+    int maxConnsTime;
+    /**
+     * The maximum connections during maxConnsTime.
+     */
+    int maxConns;
+    /**
+     * The required wait time in seconds after a successful UE initiated disconnect of a given PDN
+     * connection before the device can send a new PDN connection request for that given PDN.
+     */
+    int waitTime;
+    /**
+     * True to enable the profile, false to disable.
+     */
+    boolean enabled;
+    /**
+     * Supported APN types bitmap. See ApnTypes for the value of each bit.
+     */
+    int supportedApnTypesBitmap;
+    /**
+     * The bearer bitmap. See RadioAccessFamily for the value of each bit.
+     */
+    int bearerBitmap;
+    /**
+     * Maximum transmission unit (MTU) size in bytes for IPv4.
+     */
+    int mtuV4;
+    /**
+     * Maximum transmission unit (MTU) size in bytes for IPv6.
+     */
+    int mtuV6;
+    /**
+     * True if this data profile was used to bring up the last default (i.e internet) data
+     * connection successfully.
+     */
+    boolean preferred;
+    /**
+     * If true, modem must persist this data profile and profileId must not be set to ID_INVALID.
+     * If the same data profile exists, this data profile must overwrite it.
+     */
+    boolean persistent;
+    /**
+     * Indicates the PDU session brought up by this data profile should be always-on.
+     * An always-on PDU Session is a PDU Session for which User Plane resources have to be
+     * activated during every transition from CM-IDLE mode to CM-CONNECTED state.
+     * See 3GPP TS 23.501 section 5.6.13 for the details.
+     */
+    boolean alwaysOn;
+    /**
+     * TrafficDescriptor for which data connection needs to be established.
+     * It is used for URSP traffic matching as described in TS 24.526 Section 4.2.2.
+     * It includes an optional DNN which, if present, must be used for traffic matching --
+     * it does not specify the end point to be used for the data call. The end point is specified by
+     * apn; apn must be used as the end point if one is not specified through URSP rules.
+     */
+    TrafficDescriptor trafficDescriptor;
+}
diff --git a/radio/aidl/android/hardware/radio/data/DataRequestReason.aidl b/radio/aidl/android/hardware/radio/data/DataRequestReason.aidl
new file mode 100644
index 0000000..44b47f8
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/data/DataRequestReason.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.data;
+
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum DataRequestReason {
+    /**
+     * The reason of the data request is normal
+     */
+    NORMAL = 1,
+    /**
+     * The reason of the data request is device shutdown
+     */
+    SHUTDOWN = 2,
+    /**
+     * The reason of the data request is IWLAN data handover to another transport
+     * (e.g. from cellular to wifi or vise versa)
+     */
+    HANDOVER = 3,
+}
diff --git a/radio/aidl/android/hardware/radio/data/DataThrottlingAction.aidl b/radio/aidl/android/hardware/radio/data/DataThrottlingAction.aidl
new file mode 100644
index 0000000..e4ee444
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/data/DataThrottlingAction.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.data;
+
+@VintfStability
+@Backing(type="byte")
+@JavaDerive(toString=true)
+enum DataThrottlingAction {
+    /*
+     * Clear all existing data throttling.
+     */
+    NO_DATA_THROTTLING,
+    /**
+     * Enact secondary carrier data throttling and remove any existing data throttling on
+     * anchor carrier.
+     */
+    THROTTLE_SECONDARY_CARRIER,
+    /**
+     * Enact anchor carrier data throttling and disable data on secondary carrier if currently
+     * enabled.
+     */
+    THROTTLE_ANCHOR_CARRIER,
+    /**
+     * Immediately hold on to current level of throttling.
+     */
+    HOLD,
+}
diff --git a/radio/aidl/android/hardware/radio/data/EpsQos.aidl b/radio/aidl/android/hardware/radio/data/EpsQos.aidl
new file mode 100644
index 0000000..8965d6e
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/data/EpsQos.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.data;
+
+import android.hardware.radio.data.QosBandwidth;
+
+/**
+ * LTE/EPS Quality of Service parameters as per 3gpp spec 24.301 sec 9.9.4.3.
+ */
+@VintfStability
+@JavaDerive(toString=true)
+parcelable EpsQos {
+    /**
+     * Quality of Service Class Identifier (QCI), see 3GPP TS 23.203 and 29.212.
+     * The allowed values are standard values(1-9, 65-68, 69-70, 75, 79-80, 82-85)
+     * defined in the spec and operator specific values in the range 128-254.
+     */
+    int qci;
+    QosBandwidth downlink;
+    QosBandwidth uplink;
+}
diff --git a/radio/aidl/android/hardware/radio/data/IRadioData.aidl b/radio/aidl/android/hardware/radio/data/IRadioData.aidl
new file mode 100644
index 0000000..0171d39
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/data/IRadioData.aidl
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.data;
+
+import android.hardware.radio.AccessNetwork;
+import android.hardware.radio.data.DataProfileInfo;
+import android.hardware.radio.data.DataRequestReason;
+import android.hardware.radio.data.DataThrottlingAction;
+import android.hardware.radio.data.IRadioDataIndication;
+import android.hardware.radio.data.IRadioDataResponse;
+import android.hardware.radio.data.KeepaliveRequest;
+import android.hardware.radio.data.LinkAddress;
+import android.hardware.radio.data.SliceInfo;
+import android.hardware.radio.data.TrafficDescriptor;
+
+/**
+ * This interface is used by telephony and telecom to talk to cellular radio for data APIs.
+ * All the functions have minimum one parameter:
+ * serial: which corresponds to serial no. of request. Serial numbers must only be memorized for the
+ * duration of a method call. If clients provide colliding serials (including passing the same
+ * serial to different methods), multiple responses (one for each method call) must still be served.
+ * setResponseFunctions must work with IRadioDataResponse and IRadioDataIndication.
+ */
+@VintfStability
+oneway interface IRadioData {
+    /**
+     * Reserves an unallocated pdu session id from the pool of ids. The allocated id is returned
+     * in the response. When the id is no longer needed, call releasePduSessionId to return it to
+     * the pool.
+     *
+     * Reference: 3GPP TS 24.007 section 11.2.3.1b
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioDataResponse.allocatePduSessionIdResponse()
+     */
+    void allocatePduSessionId(in int serial);
+
+    /**
+     * Indicates that a handover was cancelled after a call to IRadioData::startHandover.
+     * Since the handover was unsuccessful, the modem retains ownership over any of the resources
+     * being transferred and is still responsible for releasing them.
+     *
+     * @param serial Serial number of request.
+     * @param id callId The identifier of the data call which is provided in SetupDataCallResult
+     *
+     * Response function is IRadioDataResponse.cancelHandoverResponse()
+     */
+    void cancelHandover(in int serial, in int callId);
+
+    /**
+     * Deactivate packet data connection and remove from the data call list. An
+     * unsolDataCallListChanged() must be sent when data connection is deactivated.
+     * Any return value other than RadioError::NONE will remove the network from the list.
+     *
+     * @param serial Serial number of request.
+     * @param cid Data call id.
+     * @param reason The request reason. Must be normal, handover, or shutdown.
+     *
+     * Response function is IRadioDataResponse.deactivateDataCallResponse()
+     */
+    void deactivateDataCall(in int serial, in int cid, in DataRequestReason reason);
+
+    /**
+     * Returns the data call list. An entry is added when a setupDataCall() is issued and removed
+     * on a deactivateDataCall(). The list is emptied when the vendor HAL crashes.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioDataResponse.getDataCallListResponse()
+     */
+    void getDataCallList(in int serial);
+
+    /**
+     * Request to get the current slicing configuration including URSP rules and NSSAIs
+     * (configured, allowed and rejected). URSP stands for UE route selection policy and is defined
+     * in 3GPP TS 24.526 Section 4.2. An NSSAI is a collection of network slices. Each network slice
+     * is identified by an S-NSSAI and is represented by the struct SliceInfo. NSSAI and S-NSSAI
+     * are defined in 3GPP TS 24.501.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioDataResponse.getSlicingConfigResponse()
+     */
+    void getSlicingConfig(in int serial);
+
+    /**
+     * Releases a pdu session id that was previously allocated using allocatePduSessionId.
+     * Reference: 3GPP TS 24.007 section 11.2.3.1b
+     *
+     * @param serial Serial number of request.
+     * @param id Pdu session id to release.
+     *
+     * Response function is IRadioDataResponse.releasePduSessionIdResponse()
+     */
+    void releasePduSessionId(in int serial, in int id);
+
+    /**
+     * When response type received from a radio indication or radio response is
+     * RadioIndicationType:UNSOLICITED_ACK_EXP or RadioResponseType:SOLICITED_ACK_EXP respectively,
+     * acknowledge the receipt of those messages by sending responseAcknowledgement().
+     */
+    void responseAcknowledgement();
+
+    /**
+     * Tells the modem whether data calls are allowed or not
+     *
+     * @param serial Serial number of request.
+     * @param allow true to allow data calls, false to disallow data calls
+     *
+     * Response function is IRadioDataResponse.setDataAllowedResponse()
+     */
+    void setDataAllowed(in int serial, in boolean allow);
+
+    /**
+     * Send data profiles of the current carrier to the modem.
+     *
+     * @param serial Serial number of request.
+     * @param profiles Array of DataProfileInfo to set.
+     *
+     * Response function is IRadioDataResponse.setDataProfileResponse()
+     */
+    void setDataProfile(in int serial, in DataProfileInfo[] profiles);
+
+    /**
+     * Control data throttling at modem.
+     * - DataThrottlingAction:NO_DATA_THROTTLING should clear any existing data throttling within
+     *   the requested completion window.
+     * - DataThrottlingAction:THROTTLE_SECONDARY_CARRIER: Remove any existing throttling on anchor
+     *   carrier and achieve maximum data throttling on secondary carrier within the requested
+     *   completion window.
+     * - DataThrottlingAction:THROTTLE_ANCHOR_CARRIER: disable secondary carrier and achieve maximum
+     *   data throttling on anchor carrier by requested completion window.
+     * - DataThrottlingAction:HOLD: Immediately hold on to current level of throttling.
+     *
+     * @param serial Serial number of request.
+     * @param dataThrottlingAction DataThrottlingAction as defined in types.hal
+     * @param completionDurationMillis window, in milliseconds, in which the requested throttling
+     *        action has to be achieved. This must be 0 when dataThrottlingAction is
+     *        DataThrottlingAction:HOLD.
+     *
+     * Response function is IRadioDataResponse.setDataThrottlingResponse()
+     */
+    void setDataThrottling(in int serial, in DataThrottlingAction dataThrottlingAction,
+            in long completionDurationMillis);
+
+    /**
+     * Set an APN to initial attach network or clear the existing initial attach APN.
+     *
+     * @param serial Serial number of request.
+     * @param dataProfileInfo Data profile containing APN settings or null to clear the existing
+     *        initial attach APN.
+     *
+     * Response function is IRadioDataResponse.setInitialAttachApnResponse()
+     */
+    void setInitialAttachApn(in int serial, in @nullable DataProfileInfo dataProfileInfo);
+
+    /**
+     * Set response functions for data radio requests and indications.
+     *
+     * @param radioDataResponse Object containing response functions
+     * @param radioDataIndication Object containing radio indications
+     */
+    void setResponseFunctions(
+            in IRadioDataResponse radioDataResponse, in IRadioDataIndication radioDataIndication);
+
+    /**
+     * Setup a packet data connection. If DataCallResponse.status returns DataCallFailCause:NONE,
+     * the data connection must be added to data calls and a unsolDataCallListChanged() must be
+     * sent. The call remains until removed by subsequent unsolDataCallIstChanged(). It may be lost
+     * due to many factors, including deactivateDataCall() being issued, the radio powered off,
+     * reception lost or even transient factors like congestion. This data call list is returned by
+     * getDataCallList() and dataCallListChanged().
+     * The Radio is expected to:
+     * - Create one data call context.
+     * - Create and configure a dedicated interface for the context.
+     * - The interface must be point to point.
+     * - The interface is configured with one or more addresses and is capable of sending and
+     *   receiving packets. The format is IP address with optional "/" prefix length (The format is
+     *   defined in RFC-4291 section 2.3). For example, "192.0.1.3", "192.0.1.11/16", or
+     *   "2001:db8::1/64". Typically one IPv4 or one IPv6 or one of each. If the prefix length is
+     *   absent, then the addresses are assumed to be point to point with IPv4 with prefix length 32
+     *   or IPv6 with prefix length 128.
+     * - Must not modify routing configuration related to this interface; routing management is
+     *   exclusively within the purview of the Android OS.
+     * - Support simultaneous data call context, with limits defined in the specifications. For LTE,
+     *   the max number of data calls is equal to the max number of EPS bearers that can be active.
+     *
+     * @param serial Serial number of request.
+     * @param accessNetwork The access network to setup the data call. If the data connection cannot
+     *        be established on the specified access network then this should respond with an error.
+     * @param dataProfileInfo Data profile info.
+     * @param roamingAllowed Indicates whether or not data roaming is allowed by the user.
+     * @param reason The request reason. Must be DataRequestReason:NORMAL or
+     *        DataRequestReason:HANDOVER.
+     * @param addresses If the reason is DataRequestReason:HANDOVER, this indicates the list of link
+     *        addresses of the existing data connection. This parameter must be ignored unless
+     *        reason is DataRequestReason:HANDOVER.
+     * @param dnses If the reason is DataRequestReason:HANDOVER, this indicates the list of DNS
+     *        addresses of the existing data connection. The format is defined in RFC-4291 section
+     *        2.2. For example, "192.0.1.3" or "2001:db8::1". This parameter must be ignored unless
+     *        reason is DataRequestReason:HANDOVER.
+     * @param pduSessionId The pdu session id to be used for this data call. A value of 0 means no
+     *        pdu session id was attached to this call. Reference: 3GPP TS 24.007 section 11.2.3.1b
+     * @param sliceInfo SliceInfo to be used for the data connection when a handover occurs from
+     *        EPDG to 5G. It is valid only when accessNetwork is AccessNetwork:NGRAN. If the slice
+     *        passed from EPDG is rejected, then the data failure cause must be
+     *        DataCallFailCause:SLICE_REJECTED.
+     * @param matchAllRuleAllowed bool to indicate if using default match-all URSP rule for this
+     *        request is allowed. If false, this request must not use the match-all URSP rule and if
+     *        a non-match-all rule is not found (or if URSP rules are not available) it should
+     *        return failure with cause DataCallFailCause:MATCH_ALL_RULE_NOT_ALLOWED. This is needed
+     *        as some requests need to have a hard failure if the intention cannot be met, for
+     *        example, a zero-rating slice.
+     *
+     * Response function is IRadioDataResponse.setupDataCallResponse()
+     */
+    void setupDataCall(in int serial, in AccessNetwork accessNetwork,
+            in DataProfileInfo dataProfileInfo, in boolean roamingAllowed,
+            in DataRequestReason reason, in LinkAddress[] addresses, in String[] dnses,
+            in int pduSessionId, in @nullable SliceInfo sliceInfo,
+            in boolean matchAllRuleAllowed);
+
+    /**
+     * Indicates that a handover to the IWLAN transport has begun. Any resources being transferred
+     * to the IWLAN transport cannot be released while a handover is underway. For example, if a
+     * pdu session id needs to be transferred to IWLAN, then the modem should not release the id
+     * while the handover is in progress. If a handover was unsuccessful, then the framework calls
+     * IRadio::cancelHandover. The modem retains ownership over any of the resources being
+     * transferred to IWLAN. If a handover was successful, the framework calls
+     * IRadio::deactivateDataCall with reason HANDOVER. The IWLAN transport now owns the transferred
+     * resources and is responsible for releasing them.
+     *
+     * @param serial Serial number of request.
+     * @param id callId The identifier of the data call which is provided in SetupDataCallResult
+     *
+     * Response function is IRadioDataResponse.startHandoverResponse()
+     */
+    void startHandover(in int serial, in int callId);
+
+    /**
+     * Start a Keepalive session (for IPsec)
+     *
+     * @param serial Serial number of request.
+     * @param keepalive A request structure containing all necessary info to describe a keepalive
+     *
+     * Response function is IRadioDataResponse.startKeepaliveResponse()
+     */
+    void startKeepalive(in int serial, in KeepaliveRequest keepalive);
+
+    /**
+     * Stop an ongoing Keepalive session (for IPsec)
+     *
+     * @param serial Serial number of request.
+     * @param sessionHandle The handle that was provided by
+     *        IRadioDataResponse.startKeepaliveResponse
+     *
+     * Response function is IRadioDataResponse.stopKeepaliveResponse()
+     */
+    void stopKeepalive(in int serial, in int sessionHandle);
+}
diff --git a/radio/aidl/android/hardware/radio/data/IRadioDataIndication.aidl b/radio/aidl/android/hardware/radio/data/IRadioDataIndication.aidl
new file mode 100644
index 0000000..938c695
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/data/IRadioDataIndication.aidl
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.data;
+
+import android.hardware.radio.RadioIndicationType;
+import android.hardware.radio.data.DataProfileInfo;
+import android.hardware.radio.data.KeepaliveStatus;
+import android.hardware.radio.data.PcoDataInfo;
+import android.hardware.radio.data.SetupDataCallResult;
+import android.hardware.radio.data.SlicingConfig;
+
+/**
+ * Interface declaring unsolicited radio indications for data APIs.
+ */
+@VintfStability
+oneway interface IRadioDataIndication {
+    /**
+     * Indicates data call contexts have changed.
+     *
+     * @param type Type of radio indication
+     * @param dcList Array of SetupDataCallResult identical to that returned by
+     *        IRadioData.getDataCallList(). It is the complete list of current data contexts
+     *        including new contexts that have been activated. A data call is only removed from
+     *        this list when any of the below conditions is matched:
+     *        - The framework sends a IRadioData.deactivateDataCall().
+     *        - The radio is powered off/on.
+     *        - Unsolicited disconnect from either modem or network side.
+     */
+    void dataCallListChanged(in RadioIndicationType type, in SetupDataCallResult[] dcList);
+
+    /**
+     * Indicates a status update for a particular Keepalive session. This must include a handle for
+     * a previous session and should include a status update regarding the state of a keepalive.
+     * Unsolicited keepalive status reports should never be PENDING as unsolicited status should
+     * only be sent when known.
+     *
+     * @param type Type of radio indication
+     * @param status Status information for a Keepalive session
+     */
+    void keepaliveStatus(in RadioIndicationType type, in KeepaliveStatus status);
+
+    /**
+     * Indicates when there is new Carrier PCO data received for a data call. Ideally only new data
+     * must be forwarded, though this is not required. Multiple boxes of carrier PCO data for a
+     * given call must result in a series of pcoData() calls.
+     *
+     * @param type Type of radio indication
+     * @param pco New PcoData
+     */
+    void pcoData(in RadioIndicationType type, in PcoDataInfo pco);
+
+    /**
+     * The modem can explicitly set SetupDataCallResult::suggestedRetryTime after a failure in
+     * IRadioData.SetupDataCall. During that time, no new calls are allowed to
+     * IRadioData.SetupDataCall that use the same APN. When IRadioDataIndication.unthrottleApn
+     * is sent, AOSP will no longer throttle calls to IRadioData.SetupDataCall for the given APN.
+     *
+     * @param type Type of radio indication
+     * @param dataProfileInfo Data profile info.
+     */
+    void unthrottleApn(in RadioIndicationType type, in DataProfileInfo dataProfileInfo);
+
+    /**
+     * Indicates the current slicing configuration including URSP rules and NSSAIs
+     * (configured, allowed and rejected). URSP stands for UE route selection policy and is defined
+     * in 3GPP TS 24.526 Section 4.2. An NSSAI is a collection of network slices. Each network slice
+     * is identified by an S-NSSAI and is represented by the struct SliceInfo. NSSAI and S-NSSAI
+     * are defined in 3GPP TS 24.501.
+     *
+     * @param type Type of radio indication
+     * @param slicingConfig Current slicing configuration
+     *
+     */
+    void slicingConfigChanged(in RadioIndicationType type, in SlicingConfig slicingConfig);
+}
diff --git a/radio/aidl/android/hardware/radio/data/IRadioDataResponse.aidl b/radio/aidl/android/hardware/radio/data/IRadioDataResponse.aidl
new file mode 100644
index 0000000..88b6c1b
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/data/IRadioDataResponse.aidl
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.data;
+
+import android.hardware.radio.RadioResponseInfo;
+import android.hardware.radio.data.KeepaliveStatus;
+import android.hardware.radio.data.SetupDataCallResult;
+import android.hardware.radio.data.SlicingConfig;
+
+/**
+ * Interface declaring response functions to solicited radio requests for data APIs.
+ */
+@VintfStability
+oneway interface IRadioDataResponse {
+    /**
+     * Acknowledge the receipt of radio request sent to the vendor. This must be sent only for
+     * radio request which take long time to respond. For more details, refer
+     * https://source.android.com/devices/tech/connect/ril.html
+     *
+     * @param serial Serial no. of the request whose acknowledgement is sent.
+     */
+    void acknowledgeRequest(in int serial);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param id The allocated id. On an error, this is set to 0.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_RESOURCES- Indicates that no pdu session ids are available
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void allocatePduSessionIdResponse(in RadioResponseInfo info, in int id);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param dcResponse Attributes of data call
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_RESOURCES
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:INVALID_CALL_ID
+     */
+    void cancelHandoverResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:REQUEST_NOT_SUPPORTED may be returned when HAL 1.2 or higher is supported.
+     *   RadioError:NONE indicates success. Any other error will remove the network from the list.
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_CALL_ID
+     *   RadioError:INVALID_STATE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:SIM_ABSENT
+     */
+    void deactivateDataCallResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param dcResponse List of SetupDataCallResult
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SIM_ABSENT
+     */
+    void getDataCallListResponse(in RadioResponseInfo info, in SetupDataCallResult[] dcResponse);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param slicingConfig Current slicing configuration
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:MODEM_ERR
+     */
+    void getSlicingConfigResponse(in RadioResponseInfo info, in SlicingConfig slicingConfig);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_RESOURCES
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void releasePduSessionIdResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:NO_MEMORY
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:MODEM_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:DEVICE_IN_USE
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void setDataAllowedResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:SUBSCRIPTION_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:SIM_ABSENT
+     */
+    void setDataProfileResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     *  Valid errors returned:
+     *  RadioError:NONE
+     *  RadioError:RADIO_NOT_AVAILABLE
+     *  RadioError:MODEM_ERR
+     *  RadioError:INVALID_ARGUMENTS
+     *  RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void setDataThrottlingResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:SUBSCRIPTION_NOT_AVAILABLE
+     *   RadioError:NO_MEMORY
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:MODEM_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:NOT_PROVISIONED
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void setInitialAttachApnResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param dcResponse SetupDataCallResult
+     *
+     * Valid errors returned:
+     *   RadioError:NONE must be returned on both success and failure of setup with the
+     *              DataCallResponse.status containing the actual status
+     *              For all other errors the DataCallResponse is ignored.
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:OP_NOT_ALLOWED_BEFORE_REG_TO_NW
+     *   RadioError:OP_NOT_ALLOWED_DURING_VOICE_CALL
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_RESOURCES if the vendor is unable handle due to resources are full.
+     *   RadioError:SIM_ABSENT
+     */
+    void setupDataCallResponse(in RadioResponseInfo info, in SetupDataCallResult dcResponse);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_RESOURCES
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:INVALID_CALL_ID
+     */
+    void startHandoverResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param status Status object containing a new handle and a current status. The status returned
+     *        here may be PENDING to indicate that the radio has not yet processed the keepalive
+     *        request.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:NO_RESOURCES
+     *   RadioError:INVALID_ARGUMENTS
+     */
+    void startKeepaliveResponse(in RadioResponseInfo info, in KeepaliveStatus status);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:INVALID_ARGUMENTS
+     */
+    void stopKeepaliveResponse(in RadioResponseInfo info);
+}
diff --git a/radio/aidl/android/hardware/radio/data/KeepaliveRequest.aidl b/radio/aidl/android/hardware/radio/data/KeepaliveRequest.aidl
new file mode 100644
index 0000000..c720de0
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/data/KeepaliveRequest.aidl
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.data;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable KeepaliveRequest {
+    /**
+     * Keepalive specified by RFC 3948 Sec. 2.3 using IPv4
+     */
+    const int TYPE_NATT_IPV4 = 0;
+    /**
+     * Keepalive specified by RFC 3948 Sec. 2.3 using IPv6
+     */
+    const int TYPE_NATT_IPV6 = 1;
+
+    /**
+     * The format of the keepalive packet
+     * Values are TYPE_
+     */
+    int type;
+    /**
+     * Source address with type = family, in network byte order
+     */
+    byte[] sourceAddress;
+    /**
+     * Source port if relevant for the given type
+     * INT_MAX: 0x7FFFFFFF denotes that the field is unused
+     */
+    int sourcePort;
+    /**
+     * Destination address with type = family, in network byte order
+     */
+    byte[] destinationAddress;
+    /**
+     * Destination if relevant for the given type
+     * INT_MAX: 0x7FFFFFFF denotes that the field is unused
+     */
+    int destinationPort;
+    /**
+     * The max interval between packets, in milliseconds
+     */
+    int maxKeepaliveIntervalMillis;
+    /**
+     * Context ID, returned in setupDataCallResponse that uniquely identifies the data call to which
+     * this keepalive must applied.
+     */
+    int cid;
+}
diff --git a/radio/aidl/android/hardware/radio/data/KeepaliveStatus.aidl b/radio/aidl/android/hardware/radio/data/KeepaliveStatus.aidl
new file mode 100644
index 0000000..0b829c4
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/data/KeepaliveStatus.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.data;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable KeepaliveStatus {
+    /**
+     * Keepalive is currently active.
+     */
+    const int CODE_ACTIVE = 0;
+    /**
+     * Keepalive is inactive, which indicates an error.
+     */
+    const int CODE_INACTIVE = 1;
+    /**
+     * Requested keepalive has not yet been processed by the modem.
+     * Only allowed in a RESPONSE message to a REQUEST.
+     */
+    const int CODE_PENDING = 2;
+
+    /**
+     * The sessionHandle provided by the API.
+     */
+    int sessionHandle;
+    /**
+     * Status for the given keepalive.
+     * Values are CODE_
+     */
+    int code;
+}
diff --git a/radio/aidl/android/hardware/radio/data/LinkAddress.aidl b/radio/aidl/android/hardware/radio/data/LinkAddress.aidl
new file mode 100644
index 0000000..12a7637
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/data/LinkAddress.aidl
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.data;
+
+/**
+ * Describes a data link address for mobile data connection.
+ */
+@VintfStability
+@JavaDerive(toString=true)
+parcelable LinkAddress {
+    const int ADDRESS_PROPERTY_NONE = 0;
+    /**
+     * Indicates this address is deprecated
+     */
+    const int ADDRESS_PROPERTY_DEPRECATED = 0x20;
+    /**
+     * The format is IP address with optional "/" prefix length (The format is defined in RFC-4291
+     * section 2.3). For example, "192.0.1.3", "192.0.1.11/16", or "2001:db8::1/64". Typically one
+     * IPv4 or one IPv6 or one of each. If the prefix length is absent, then the addresses are
+     * assumed to be point to point with IPv4 with prefix length 32 or IPv6 with prefix length 128.
+     */
+    String address;
+    /**
+     * The properties of the link address, as defined in if_addr.h in the Linux kernel.
+     * Values are ADDRESS_PROPERTY_
+     */
+    int addressProperties;
+    /**
+     * The time, as reported by SystemClock.elapsedRealtime(), when this link address will be or
+     * was deprecated. -1 indicates this information is not available. At the time existing
+     * connections can still use this address until it expires, but new connections should use the
+     * new address. LONG_MAX(0x7FFFFFFFFFFFFFFF) indicates this link address will never be
+     * deprecated.
+     */
+    long deprecationTime;
+    /**
+     * The time, as reported by SystemClock.elapsedRealtime(), when this link address will expire
+     * and be removed from the interface. -1 indicates this information is not available.
+     * LONG_MAX(0x7FFFFFFFFFFFFFFF) indicates this link address will never expire.
+     */
+    long expirationTime;
+}
diff --git a/radio/aidl/android/hardware/radio/data/NrQos.aidl b/radio/aidl/android/hardware/radio/data/NrQos.aidl
new file mode 100644
index 0000000..af8ab83
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/data/NrQos.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.data;
+
+import android.hardware.radio.data.QosBandwidth;
+
+/**
+ * 5G Quality of Service parameters as per 3gpp spec 24.501 sec 9.11.4.12
+ */
+@VintfStability
+@JavaDerive(toString=true)
+parcelable NrQos {
+    const byte FLOW_ID_RANGE_MIN = 1;
+    const byte FLOW_ID_RANGE_MAX = 63;
+
+    /**
+     * 5G QOS Identifier (5QI), see 3GPP TS 24.501 and 23.501. The allowed values are standard
+     * values (1-9, 65-68, 69-70, 75, 79-80, 82-85) defined in the spec and operator specific values
+     * in the range 128-254.
+     */
+    int fiveQi;
+    QosBandwidth downlink;
+    QosBandwidth uplink;
+    /**
+     * QOS flow identifier of the QOS flow description in the range
+     * (FLOW_ID_RANGE_MIN, FLOW_ID_RANGE_MAX)
+     */
+    byte qfi;
+    char averagingWindowMs;
+}
diff --git a/radio/aidl/android/hardware/radio/data/OsAppId.aidl b/radio/aidl/android/hardware/radio/data/OsAppId.aidl
new file mode 100644
index 0000000..88e7832
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/data/OsAppId.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.data;
+
+/**
+ * This struct represents the OsId + OsAppId as defined in TS 24.526 Section 5.2
+ */
+@VintfStability
+@JavaDerive(toString=true)
+parcelable OsAppId {
+    /**
+     * Byte array representing OsId + OsAppId. The minimum length of the array is 18 and maximum
+     * length is 272 (16 bytes for OsId + 1 byte for OsAppId length + up to 255 bytes for OsAppId).
+     */
+    byte[] osAppId;
+}
diff --git a/radio/aidl/android/hardware/radio/data/PcoDataInfo.aidl b/radio/aidl/android/hardware/radio/data/PcoDataInfo.aidl
new file mode 100644
index 0000000..38a821f
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/data/PcoDataInfo.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.data;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable PcoDataInfo {
+    /**
+     * Context ID, uniquely identifies this call
+     */
+    int cid;
+    /**
+     * One of the PDP_type values in TS 27.007 section 10.1.1. For example, "IP", "IPV6", "IPV4V6"
+     */
+    String bearerProto;
+    /**
+     * The protocol ID for this box. Note that only IDs from FF00H - FFFFH are accepted.
+     * If more than one is included from the network, multiple calls must be made to send
+     * all of them.
+     */
+    int pcoId;
+    /**
+     * Carrier-defined content. It is binary, opaque and loosely defined in LTE Layer 3 spec 24.008
+     */
+    byte[] contents;
+}
diff --git a/radio/aidl/android/hardware/radio/data/PdpProtocolType.aidl b/radio/aidl/android/hardware/radio/data/PdpProtocolType.aidl
new file mode 100644
index 0000000..792a503
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/data/PdpProtocolType.aidl
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.data;
+
+/**
+ * Specifies the type of packet data protocol which is defined in TS 27.007 section 10.1.1.
+ */
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum PdpProtocolType {
+    /**
+     * Unknown protocol
+     */
+    UNKNOWN = -1,
+    /**
+     * Internet protocol
+     */
+    IP = 0,
+    /**
+     * Internet protocol, version 6
+     */
+    IPV6 = 1,
+    /**
+     * Virtual PDP type introduced to handle dual IP stack UE capability.
+     */
+    IPV4V6 = 2,
+    /**
+     * Point to point protocol
+     */
+    PPP = 3,
+    /**
+     * Transfer of Non-IP data to external packet data network
+     */
+    NON_IP = 4,
+    /**
+     * Transfer of Unstructured data to the Data Network via N6
+     */
+    UNSTRUCTURED = 5,
+}
diff --git a/radio/aidl/android/hardware/radio/data/PortRange.aidl b/radio/aidl/android/hardware/radio/data/PortRange.aidl
new file mode 100644
index 0000000..5c83ca4
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/data/PortRange.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.data;
+
+/**
+ * Defines range of ports. start and end are the first and last port numbers (inclusive) in the
+ * range. Both start and end are in PORT_RANGE_MIN to PORT_RANGE_MAX range. A single port shall
+ * be represented by the same start and end value.
+ */
+@VintfStability
+@JavaDerive(toString=true)
+parcelable PortRange {
+    const int PORT_RANGE_MIN = 20;
+    const int PORT_RANGE_MAX = 65535;
+
+    int start;
+    int end;
+}
diff --git a/radio/aidl/android/hardware/radio/data/Qos.aidl b/radio/aidl/android/hardware/radio/data/Qos.aidl
new file mode 100644
index 0000000..d9ab9e7
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/data/Qos.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.data;
+
+import android.hardware.radio.data.EpsQos;
+import android.hardware.radio.data.NrQos;
+
+/**
+ * EPS or NR QOS parameters
+ */
+@VintfStability
+@JavaDerive(toString=true)
+union Qos {
+    boolean noinit;
+    EpsQos eps;
+    NrQos nr;
+}
diff --git a/radio/aidl/android/hardware/radio/data/QosBandwidth.aidl b/radio/aidl/android/hardware/radio/data/QosBandwidth.aidl
new file mode 100644
index 0000000..e841548
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/data/QosBandwidth.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.data;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable QosBandwidth {
+    /**
+     * Maximum bit rate possible on the bearer
+     */
+    int maxBitrateKbps;
+    /**
+     * Minimum bit rate that is guaranteed to be provided by the network
+     */
+    int guaranteedBitrateKbps;
+}
diff --git a/radio/aidl/android/hardware/radio/data/QosFilter.aidl b/radio/aidl/android/hardware/radio/data/QosFilter.aidl
new file mode 100644
index 0000000..f5dc7ec
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/data/QosFilter.aidl
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.data;
+
+import android.hardware.radio.data.PortRange;
+import android.hardware.radio.data.QosFilterIpsecSpi;
+import android.hardware.radio.data.QosFilterIpv6FlowLabel;
+import android.hardware.radio.data.QosFilterTypeOfService;
+
+/**
+ * See 3gpp 24.008 10.5.6.12 and 3gpp 24.501 9.11.4.13
+ */
+@VintfStability
+@JavaDerive(toString=true)
+parcelable QosFilter {
+    const byte DIRECTION_DOWNLINK = 0;
+    const byte DIRECTION_UPLINK = 1;
+    const byte DIRECTION_BIDIRECTIONAL = 2;
+
+    /**
+     * No protocol specified
+     */
+    const byte PROTOCOL_UNSPECIFIED = -1;
+    /**
+     * Transmission Control Protocol
+     */
+    const byte PROTOCOL_TCP = 6;
+    /**
+     * User Datagram Protocol
+     */
+    const byte PROTOCOL_UDP = 17;
+    /**
+     * Encapsulating Security Payload Protocol
+     */
+    const byte PROTOCOL_ESP = 50;
+    /**
+     * Authentication Header
+     */
+    const byte PROTOCOL_AH = 51;
+
+    /**
+     * Local and remote IP addresses, typically one IPv4 or one IPv6 or one of each. Addresses could
+     * be with optional "/" prefix length, e.g.,"192.0.1.3" or "192.0.1.11/16 2001:db8::1/64".
+     * If the prefix length is absent the addresses are assumed to be point to point with IPv4
+     * having a prefix length of 32 and IPv6 128.
+     */
+    String[] localAddresses;
+    String[] remoteAddresses;
+    /**
+     * Local port/range
+     */
+    @nullable PortRange localPort;
+    /**
+     * Remote port/range
+     */
+    @nullable PortRange remotePort;
+    /**
+     * Next header QoS protocol numbers defined by IANA, RFC 5237
+     * Values are PROTOCOL_
+     */
+    byte protocol;
+    /**
+     * Type of service value or mask as defined in RFC 1349
+     */
+    QosFilterTypeOfService tos;
+    /**
+     * IPv6 flow label as defined in RFC 6437
+     */
+    QosFilterIpv6FlowLabel flowLabel;
+    /**
+     * IPSec security parameter index
+     */
+    QosFilterIpsecSpi spi;
+    /**
+     * Filter direction
+     * Values are DIRECTION_
+     */
+    byte direction;
+    /**
+     * Specifies the order in which the filter needs to be matched. A lower numerical (positive)
+     * value has a higher precedence. Set -1 when unspecified.
+     */
+    int precedence;
+}
diff --git a/radio/aidl/android/hardware/radio/data/QosFilterIpsecSpi.aidl b/radio/aidl/android/hardware/radio/data/QosFilterIpsecSpi.aidl
new file mode 100644
index 0000000..5059c28
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/data/QosFilterIpsecSpi.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.data;
+
+@VintfStability
+@JavaDerive(toString=true)
+union QosFilterIpsecSpi {
+    boolean noinit;
+    int value;
+}
diff --git a/radio/aidl/android/hardware/radio/data/QosFilterIpv6FlowLabel.aidl b/radio/aidl/android/hardware/radio/data/QosFilterIpv6FlowLabel.aidl
new file mode 100644
index 0000000..6f14934
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/data/QosFilterIpv6FlowLabel.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.data;
+
+@VintfStability
+@JavaDerive(toString=true)
+union QosFilterIpv6FlowLabel {
+    boolean noinit;
+    int value;
+}
diff --git a/radio/aidl/android/hardware/radio/data/QosFilterTypeOfService.aidl b/radio/aidl/android/hardware/radio/data/QosFilterTypeOfService.aidl
new file mode 100644
index 0000000..f5770a4
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/data/QosFilterTypeOfService.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.data;
+
+@VintfStability
+@JavaDerive(toString=true)
+union QosFilterTypeOfService {
+    boolean noinit;
+    byte value;
+}
diff --git a/radio/aidl/android/hardware/radio/data/QosSession.aidl b/radio/aidl/android/hardware/radio/data/QosSession.aidl
new file mode 100644
index 0000000..770b124
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/data/QosSession.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.data;
+
+import android.hardware.radio.data.Qos;
+import android.hardware.radio.data.QosFilter;
+
+/**
+ * QOS session associated with a dedicated bearer
+ */
+@VintfStability
+@JavaDerive(toString=true)
+parcelable QosSession {
+    /**
+     * Unique ID of the QoS session within the data call
+     */
+    int qosSessionId;
+    /**
+     * QOS attributes
+     */
+    Qos qos;
+    /**
+     * List of QOS filters associated with this session
+     */
+    QosFilter[] qosFilters;
+}
diff --git a/radio/aidl/android/hardware/radio/data/RouteSelectionDescriptor.aidl b/radio/aidl/android/hardware/radio/data/RouteSelectionDescriptor.aidl
new file mode 100644
index 0000000..14b0ffc
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/data/RouteSelectionDescriptor.aidl
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.data;
+
+import android.hardware.radio.data.PdpProtocolType;
+import android.hardware.radio.data.SliceInfo;
+
+/**
+ * This struct represents a single route selection descriptor as defined in 3GPP TS 24.526.
+ */
+@VintfStability
+@JavaDerive(toString=true)
+parcelable RouteSelectionDescriptor {
+    const byte SSC_MODE_UNKNOWN = -1;
+    const byte SSC_MODE_1 = 1;
+    const byte SSC_MODE_2 = 2;
+    const byte SSC_MODE_3 = 3;
+
+    /**
+     * Precedence value in the range of 0 to 255. Higher value has lower precedence.
+     */
+    byte precedence;
+    /**
+     * Valid values are IP, IPV6, IPV4V6, and UNKNOWN.
+     */
+    PdpProtocolType sessionType;
+    /**
+     * Session and service continuity mode as defined in 3GPP TS 23.501.
+     * Valid values are SSC_MODE_
+     */
+    byte sscMode;
+    /**
+     * There can be 0 or more SliceInfo specified in a route descriptor.
+     */
+    SliceInfo[] sliceInfo;
+    /**
+     * DNN stands for Data Network Name and represents an APN as defined in 3GPP TS 23.003.
+     * There can be 0 or more DNNs specified in a route descriptor.
+     */
+    String[] dnn;
+}
diff --git a/radio/aidl/android/hardware/radio/data/SetupDataCallResult.aidl b/radio/aidl/android/hardware/radio/data/SetupDataCallResult.aidl
new file mode 100644
index 0000000..fee54ac
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/data/SetupDataCallResult.aidl
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.data;
+
+import android.hardware.radio.data.DataCallFailCause;
+import android.hardware.radio.data.LinkAddress;
+import android.hardware.radio.data.PdpProtocolType;
+import android.hardware.radio.data.Qos;
+import android.hardware.radio.data.QosSession;
+import android.hardware.radio.data.SliceInfo;
+import android.hardware.radio.data.TrafficDescriptor;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable SetupDataCallResult {
+    /**
+     * Indicates the data connection is inactive.
+     */
+    const int DATA_CONNECTION_STATUS_INACTIVE = 0;
+    /**
+     * Indicates the data connection is active with physical link dormant.
+     */
+    const int DATA_CONNECTION_STATUS_DORMANT = 1;
+    /**
+     * Indicates the data connection is active with physical link up.
+     */
+    const int DATA_CONNECTION_STATUS_ACTIVE = 2;
+
+    /**
+     * On data handover failure, fallback to the source data transport when the fail cause is due
+     * to a hand off preference change.
+     */
+    const byte HANDOVER_FAILURE_MODE_LEGACY = 0;
+    /**
+     * On data handover failure, fallback to the source data transport.
+     */
+    const byte HANDOVER_FAILURE_MODE_DO_FALLBACK = 1;
+    /**
+     * On data handover failure, retry the handover instead of falling back to the source data
+     * transport.
+     */
+    const byte HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_HANDOVER = 2;
+    /**
+     * On data handover failure, setup a new data connection by sending a normal request to the
+     * underlying data service.
+     */
+    const byte HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_SETUP_NORMAL = 3;
+
+    /**
+     * Data call fail cause. DataCallFailCause.NONE if no error.
+     */
+    DataCallFailCause cause;
+    /**
+     * If cause is not DataCallFailCause.NONE, this field indicates the network suggested data
+     * retry back-off time in milliseconds. Negative value indicates network does not give any
+     * suggestion. 0 indicates retry should be performed immediately. 0x7fffffffffffffff indicates
+     * the device should not retry data setup anymore. During this time, no calls to
+     * IRadioData.setupDataCall for this APN will be made unless IRadioDataIndication.unthrottleApn
+     * is sent with the same APN.
+     */
+    long suggestedRetryTime;
+    /**
+     * Context ID, uniquely identifies this data connection.
+     */
+    int cid;
+    /**
+     * Data connection active status.
+     * Values are DATA_CONNECTION_STATUS_
+     */
+    int active;
+    /**
+     * PDP protocol type. If cause is DataCallFailCause.ONLY_SINGLE_BEARER_ALLOWED, this is the
+     * protocol type supported, such as "IP" or "IPV6".
+     */
+    PdpProtocolType type;
+    /**
+     * The network interface name.
+     */
+    String ifname;
+    /**
+     * List of link address.
+     */
+    LinkAddress[] addresses;
+    /**
+     * List of DNS server addresses, e.g., "192.0.1.3" or "192.0.1.11 2001:db8::1". Empty if no dns
+     * server addresses returned.
+     */
+    String[] dnses;
+    /**
+     * List of default gateway addresses, e.g., "192.0.1.3" or "192.0.1.11 2001:db8::1".
+     * When empty, the addresses represent point to point connections.
+     */
+    String[] gateways;
+    /**
+     * List of P-CSCF (Proxy Call State Control Function) addresses via PCO (Protocol Configuration
+     * Option), e.g., "2001:db8::1 2001:db8::2 2001:db8::3". Empty if not IMS client.
+     */
+    String[] pcscf;
+    /**
+     * MTU received from network for IPv4.
+     * Value <= 0 means network has either not sent a value or sent an invalid value.
+     */
+    int mtuV4;
+    /**
+     * MTU received from network for IPv6.
+     * Value <= 0 means network has either not sent a value or sent an invalid value.
+     */
+    int mtuV6;
+    /**
+     * Default bearer QoS. Applicable to LTE and NR
+     */
+    Qos defaultQos;
+    /**
+     * Active QOS sessions of the dedicated bearers. Applicable to PDNs that support dedicated
+     * bearers.
+     */
+    QosSession[] qosSessions;
+    /**
+     * Specifies the fallback mode on an IWLAN handover failure.
+     * Values are HANDOVER_FAILURE_MODE_
+     */
+    byte handoverFailureMode;
+    /**
+     * The allocated pdu session id for this data call. A value of 0 means no pdu session id was
+     * attached to this call. Reference: 3GPP TS 24.007 section 11.2.3.1b.
+     */
+    int pduSessionId;
+    /**
+     * Slice used for this data call. It is valid only when this data call is on AccessNetwork:NGRAN
+     */
+    @nullable SliceInfo sliceInfo;
+    /**
+     * TrafficDescriptors for which this data call must be used. It only includes the TDs for which
+     * a data call has been requested so far; it is not an exhaustive list.
+     */
+    TrafficDescriptor[] trafficDescriptors;
+}
diff --git a/radio/aidl/android/hardware/radio/data/SliceInfo.aidl b/radio/aidl/android/hardware/radio/data/SliceInfo.aidl
new file mode 100644
index 0000000..7ad7fc3
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/data/SliceInfo.aidl
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.data;
+
+/**
+ * This struct represents a S-NSSAI as defined in 3GPP TS 24.501.
+ */
+@VintfStability
+@JavaDerive(toString=true)
+parcelable SliceInfo {
+    /*
+     * Not specified
+     */
+    const byte SERVICE_TYPE_NONE = 0;
+    /*
+     * Slice suitable for the handling of 5G enhanced Mobile Broadband
+     */
+    const byte SERVICE_TYPE_EMBB = 1;
+    /**
+     * Slice suitable for the handling of ultra-reliable low latency communications
+     */
+    const byte SERVICE_TYPE_URLLC = 2;
+    /*
+     * Slice suitable for the handling of massive IoT
+     */
+    const byte SERVICE_TYPE_MIOT = 3;
+
+    const byte STATUS_UNKNOWN = 0;
+    /**
+     * Configured but not allowed or rejected yet
+     */
+    const byte STATUS_CONFIGURED = 1;
+    /**
+     * Allowed to be used
+     */
+    const byte STATUS_ALLOWED = 2;
+    /**
+     * Rejected because not available in PLMN
+     */
+    const byte STATUS_REJECTED_NOT_AVAILABLE_IN_PLMN = 3;
+    /**
+     * Rejected because not available in reg area
+     */
+    const byte STATUS_REJECTED_NOT_AVAILABLE_IN_REG_AREA = 4;
+    /**
+     * Considered valid when configured/allowed slices are not available
+     */
+    const byte STATUS_DEFAULT_CONFIGURED = 5;
+
+    /**
+     * The type of service provided by the slice. See: 3GPP TS 24.501 Section 9.11.2.8.
+     * Values are SERVICE_TYPE_
+     */
+    byte sliceServiceType;
+    /**
+     * Slice differentiator is the identifier of a slice that has SliceServiceType as SST. A value
+     * of -1 indicates that there is no corresponding SliceInfo of the HPLMN.
+     * See: 3GPP TS 24.501 Section 9.11.2.8.
+     */
+    int sliceDifferentiator;
+    /**
+     * This SST corresponds to a SliceInfo (S-NSSAI) of the HPLMN; the SST is mapped to this value.
+     * See: 3GPP TS 24.501 Section 9.11.2.8.
+     * Values are SERVICE_TYPE_
+     */
+    byte mappedHplmnSst;
+    /**
+     * Present only if both sliceDifferentiator and mappedHplmnSst are also present. This SD
+     * corresponds to a SliceInfo (S-NSSAI) of the HPLMN; sliceDifferentiator is mapped to this
+     * value. A value of -1 indicates that there is no corresponding SliceInfo of the HPLMN.
+     * See: 3GPP TS 24.501 Section 9.11.2.8.
+     */
+    int mappedHplmnSd;
+    /**
+     * Field to indicate the current status of the slice.
+     * Values are STATUS_
+     */
+    byte status;
+}
diff --git a/radio/aidl/android/hardware/radio/data/SlicingConfig.aidl b/radio/aidl/android/hardware/radio/data/SlicingConfig.aidl
new file mode 100644
index 0000000..e94b58c
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/data/SlicingConfig.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.data;
+
+import android.hardware.radio.data.SliceInfo;
+import android.hardware.radio.data.UrspRule;
+
+/**
+ * This struct represents the current slicing configuration.
+ */
+@VintfStability
+@JavaDerive(toString=true)
+parcelable SlicingConfig {
+    /**
+     * This vector contains the current URSP rules. Empty vector indicates no rules are configured.
+     */
+    UrspRule[] urspRules;
+    /**
+     * List of all slices.
+     */
+    SliceInfo[] sliceInfo;
+}
diff --git a/radio/aidl/android/hardware/radio/data/TrafficDescriptor.aidl b/radio/aidl/android/hardware/radio/data/TrafficDescriptor.aidl
new file mode 100644
index 0000000..2c117a5
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/data/TrafficDescriptor.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.data;
+
+import android.hardware.radio.data.OsAppId;
+
+/**
+ * This struct represents a traffic descriptor. A valid struct must have at least one of the
+ * optional values present. This is based on the definition of traffic descriptor in
+ * TS 24.526 Section 5.2.
+ */
+@VintfStability
+@JavaDerive(toString=true)
+parcelable TrafficDescriptor {
+    /**
+     * DNN stands for Data Network Name and represents an APN as defined in 3GPP TS 23.003.
+     */
+    @nullable String dnn;
+    /**
+     * Indicates the OsId + OsAppId (used as category in Android).
+     */
+    @nullable OsAppId osAppId;
+}
diff --git a/radio/aidl/android/hardware/radio/data/UrspRule.aidl b/radio/aidl/android/hardware/radio/data/UrspRule.aidl
new file mode 100644
index 0000000..0499edd
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/data/UrspRule.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.data;
+
+import android.hardware.radio.data.RouteSelectionDescriptor;
+import android.hardware.radio.data.TrafficDescriptor;
+
+/**
+ * This struct represents a single URSP rule as defined in 3GPP TS 24.526.
+ */
+@VintfStability
+@JavaDerive(toString=true)
+parcelable UrspRule {
+    /**
+     * Precedence value in the range of 0 to 255. Higher value has lower precedence.
+     */
+    int precedence;
+    /**
+     * Used as a matcher for network requests.
+     */
+    TrafficDescriptor[] trafficDescriptors;
+    /**
+     * List of routes (connection parameters) that must be used for requests matching a
+     * trafficDescriptor.
+     */
+    RouteSelectionDescriptor[] routeSelectionDescriptor;
+}
diff --git a/radio/aidl/android/hardware/radio/messaging/CdmaBroadcastSmsConfigInfo.aidl b/radio/aidl/android/hardware/radio/messaging/CdmaBroadcastSmsConfigInfo.aidl
new file mode 100644
index 0000000..4173f15
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/messaging/CdmaBroadcastSmsConfigInfo.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.messaging;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable CdmaBroadcastSmsConfigInfo {
+    /**
+     * Defines a broadcast message identifier whose value is 0x0000 - 0xFFFF as defined in
+     * C.R1001G 9.3.1 and 9.3.2.
+     */
+    int serviceCategory;
+    /**
+     * Language code of broadcast message whose value is 0x00 - 0x07 as defined in C.R1001G 9.2.
+     */
+    int language;
+    /**
+     * Selected false means message types specified in serviceCategory are not accepted,
+     * while true means accepted.
+     */
+    boolean selected;
+}
diff --git a/radio/aidl/android/hardware/radio/messaging/CdmaSmsAck.aidl b/radio/aidl/android/hardware/radio/messaging/CdmaSmsAck.aidl
new file mode 100644
index 0000000..85ef692
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/messaging/CdmaSmsAck.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.messaging;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable CdmaSmsAck {
+    boolean errorClass;
+    /**
+     * SMS cause code as defined in N.S00005, 6.5.2.125.
+     * Currently, only 35 (resource shortage) and 39 (other terminal problem) are reported.
+     */
+    int smsCauseCode;
+}
diff --git a/radio/aidl/android/hardware/radio/messaging/CdmaSmsAddress.aidl b/radio/aidl/android/hardware/radio/messaging/CdmaSmsAddress.aidl
new file mode 100644
index 0000000..8e521df
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/messaging/CdmaSmsAddress.aidl
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.messaging;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable CdmaSmsAddress {
+    /**
+     * DTMF digits
+     */
+    const int DIGIT_MODE_FOUR_BIT = 0;
+    const int DIGIT_MODE_EIGHT_BIT = 1;
+
+    const int NUMBER_PLAN_UNKNOWN = 0;
+    /**
+     * CCITT E.164 and E.163, including ISDN plan
+     */
+    const int NUMBER_PLAN_TELEPHONY = 1;
+    const int NUMBER_PLAN_RESERVED_2 = 2;
+    /**
+     * CCITT X.121
+     */
+    const int NUMBER_PLAN_DATA = 3;
+    /**
+     * CCITT F.69
+     */
+    const int NUMBER_PLAN_TELEX = 4;
+    const int NUMBER_PLAN_RESERVED_5 = 5;
+    const int NUMBER_PLAN_RESERVED_6 = 6;
+    const int NUMBER_PLAN_RESERVED_7 = 7;
+    const int NUMBER_PLAN_RESERVED_8 = 8;
+    const int NUMBER_PLAN_PRIVATE = 9;
+    const int NUMBER_PLAN_RESERVED_10 = 10;
+    const int NUMBER_PLAN_RESERVED_11 = 11;
+    const int NUMBER_PLAN_RESERVED_12 = 12;
+    const int NUMBER_PLAN_RESERVED_13 = 13;
+    const int NUMBER_PLAN_RESERVED_14 = 14;
+    const int NUMBER_PLAN_RESERVED_15 = 15;
+
+    const int NUMBER_TYPE_UNKNOWN = 0;
+    /**
+     * INTERNATIONAL is used when number mode is not data network address. DATA_IP is used when the
+     * number mode is data network address.
+     */
+    const int NUMBER_TYPE_INTERNATIONAL_OR_DATA_IP = 1;
+    /**
+     * NATIONAL is used when the number mode is not data netework address. INTERNET_MAIL is used
+     * when the number mode is data network address. For INTERNET_MAIL, in the address data
+     * "digits", each byte contains an ASCII character. Examples are: "x@y.com,a@b.com"
+     * Ref TIA/EIA-637A 3.4.3.3
+     */
+    const int NUMBER_TYPE_NATIONAL_OR_INTERNET_MAIL = 2;
+    const int NUMBER_TYPE_NETWORK = 3;
+    const int NUMBER_TYPE_SUBSCRIBER = 4;
+    /**
+     * GSM SMS: address value is GSM 7-bit chars
+     */
+    const int NUMBER_TYPE_ALPHANUMERIC = 5;
+    const int NUMBER_TYPE_ABBREVIATED = 6;
+    const int NUMBER_TYPE_RESERVED_7 = 7;
+
+    /**
+     * CdmaSmsDigitMode is of two types : 4 bit and 8 bit.
+     * For 4-bit type, only "digits" field defined below in this struct is used.
+     * Values are DIGIT_MODE_
+     */
+    int digitMode;
+    /**
+     * Used only when digitMode is 8-bit.
+     */
+    boolean isNumberModeDataNetwork;
+    /**
+     * Used only when digitMode is 8-bit. To specify an international address, use the following:
+     * digitMode = EIGHT_BIT
+     * isNumberModeDataNetwork = true
+     * numberType = INTERNATIONAL_OR_DATA_IP
+     * numberPlan = TELEPHONY
+     * digits = ASCII digits, e.g. '1', '2', '3', '4', and '5'
+     * Values are NUMBER_TYPE_
+     */
+    int numberType;
+    /**
+     * Used only when digitMode is 8-bit.
+     * Values are NUMBER_PLAN_
+     */
+    int numberPlan;
+    /**
+     * Each byte in this array represents a 4 bit or 8-bit digit of address data.
+     */
+    byte[] digits;
+}
diff --git a/radio/aidl/android/hardware/radio/messaging/CdmaSmsMessage.aidl b/radio/aidl/android/hardware/radio/messaging/CdmaSmsMessage.aidl
new file mode 100644
index 0000000..d4fb26f
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/messaging/CdmaSmsMessage.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.messaging;
+
+import android.hardware.radio.messaging.CdmaSmsAddress;
+import android.hardware.radio.messaging.CdmaSmsSubaddress;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable CdmaSmsMessage {
+    int teleserviceId;
+    boolean isServicePresent;
+    int serviceCategory;
+    CdmaSmsAddress address;
+    CdmaSmsSubaddress subAddress;
+    /**
+     * 3GPP2 C.S0015-B, v2.0
+     */
+    byte[] bearerData;
+}
diff --git a/radio/aidl/android/hardware/radio/messaging/CdmaSmsSubaddress.aidl b/radio/aidl/android/hardware/radio/messaging/CdmaSmsSubaddress.aidl
new file mode 100644
index 0000000..18e5837
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/messaging/CdmaSmsSubaddress.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.messaging;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable CdmaSmsSubaddress {
+    /**
+     * CCITT X.213 or ISO 8348 AD2
+     */
+    const int SUBADDRESS_TYPE_NSAP = 0;
+    /**
+     * e.g. X.25
+     */
+    const int SUBADDRESS_TYPE_USER_SPECIFIED = 1;
+
+    /**
+     * Values are SUBADDRESS_TYPE_
+     */
+    int subaddressType;
+    /**
+     * True means the last byte's lower 4 bits must be ignored
+     */
+    boolean odd;
+    /**
+     * Each byte represents an 8-bit digit of subaddress data
+     */
+    byte[] digits;
+}
diff --git a/radio/aidl/android/hardware/radio/messaging/CdmaSmsWriteArgs.aidl b/radio/aidl/android/hardware/radio/messaging/CdmaSmsWriteArgs.aidl
new file mode 100644
index 0000000..4191985
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/messaging/CdmaSmsWriteArgs.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.messaging;
+
+import android.hardware.radio.messaging.CdmaSmsMessage;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable CdmaSmsWriteArgs {
+    const int STATUS_REC_UNREAD = 0;
+    const int STATUS_REC_READ = 1;
+    const int STATUS_STO_UNSENT = 2;
+    const int STATUS_STO_SENT = 3;
+
+    /**
+     * Status of message. See TS 27.005 3.1
+     * Values are STATUS_
+     */
+    int status;
+    CdmaSmsMessage message;
+}
diff --git a/radio/aidl/android/hardware/radio/messaging/GsmBroadcastSmsConfigInfo.aidl b/radio/aidl/android/hardware/radio/messaging/GsmBroadcastSmsConfigInfo.aidl
new file mode 100644
index 0000000..5138c3c
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/messaging/GsmBroadcastSmsConfigInfo.aidl
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.messaging;
+
+/**
+ * Which types of Cell Broadcast Message (CBM) are to be received by the ME
+ */
+@VintfStability
+@JavaDerive(toString=true)
+parcelable GsmBroadcastSmsConfigInfo {
+    /**
+     * Beginning of the range of CBM message identifiers whose value is 0x0000 - 0xFFFF as defined
+     * in TS 23.041 9.4.1.2.2 for GMS and 9.4.4.2.2 for UMTS.
+     * All other values must be treated as empty CBM message ID.
+     */
+    int fromServiceId;
+    /**
+     * End of the range of CBM message identifiers whose value is 0x0000 - 0xFFFF as defined in
+     * TS 23.041 9.4.1.2.2 for GMS and 9.4.4.2.2 for UMTS.
+     * All other values must be treated as empty CBM message ID.
+     */
+    int toServiceId;
+    /**
+     * Beginning of the range of CBM data coding schemes whose value is 0x00 - 0xFF as defined in
+     * TS 23.041 9.4.1.2.3 for GMS and 9.4.4.2.3 for UMTS.
+     * All other values must be treated as empty CBM data coding scheme.
+     */
+    int fromCodeScheme;
+    /**
+     * End of the range of CBM data coding schemes whose value is 0x00 - 0xFF as defined in
+     * TS 23.041 9.4.1.2.3 for GMS and 9.4.4.2.3 for UMTS.
+     * All other values must be treated as empty CBM data coding scheme.
+     */
+    int toCodeScheme;
+    /**
+     * False means message types specified in <fromServiceId, toServiceId>
+     * and <fromCodeScheme, toCodeScheme> are not accepted, while true means accepted.
+     */
+    boolean selected;
+}
diff --git a/radio/aidl/android/hardware/radio/messaging/GsmSmsMessage.aidl b/radio/aidl/android/hardware/radio/messaging/GsmSmsMessage.aidl
new file mode 100644
index 0000000..ee62d95
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/messaging/GsmSmsMessage.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.messaging;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable GsmSmsMessage {
+    /**
+     * SMSC address in GSM BCD format prefixed by a length byte (as expected by TS 27.005)
+     * or empty string for default SMSC
+     */
+    String smscPdu;
+    /**
+     * SMS in PDU format as an ASCII hex string less the SMSC address.
+     * TP-Layer-Length is be "strlen(pdu)/2
+     */
+    String pdu;
+}
diff --git a/radio/aidl/android/hardware/radio/messaging/IRadioMessaging.aidl b/radio/aidl/android/hardware/radio/messaging/IRadioMessaging.aidl
new file mode 100644
index 0000000..8bd84a3
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/messaging/IRadioMessaging.aidl
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.messaging;
+
+import android.hardware.radio.messaging.CdmaBroadcastSmsConfigInfo;
+import android.hardware.radio.messaging.CdmaSmsAck;
+import android.hardware.radio.messaging.CdmaSmsMessage;
+import android.hardware.radio.messaging.CdmaSmsWriteArgs;
+import android.hardware.radio.messaging.GsmBroadcastSmsConfigInfo;
+import android.hardware.radio.messaging.GsmSmsMessage;
+import android.hardware.radio.messaging.IRadioMessagingIndication;
+import android.hardware.radio.messaging.IRadioMessagingResponse;
+import android.hardware.radio.messaging.ImsSmsMessage;
+import android.hardware.radio.messaging.SmsAcknowledgeFailCause;
+import android.hardware.radio.messaging.SmsWriteArgs;
+
+/**
+ * This interface is used by telephony and telecom to talk to cellular radio for messaging APIs.
+ * All the functions have minimum one parameter:
+ * serial: which corresponds to serial no. of request. Serial numbers must only be memorized for the
+ * duration of a method call. If clients provide colliding serials (including passing the same
+ * serial to different methods), multiple responses (one for each method call) must still be served.
+ * setResponseFunctions must work with IRadioMessagingResponse and IRadioMessagingIndication.
+ */
+@VintfStability
+oneway interface IRadioMessaging {
+    /**
+     * Acknowledge successful or failed receipt of SMS previously indicated via unsol
+     * responseNewSms(), including acknowledgement TPDU to send as the RP-User-Data element of the
+     * RP-ACK or RP-ERROR PDU.
+     *
+     * @param serial Serial number of request.
+     * @param success true on successful receipt (send RP-ACK)
+     *        false on failed receipt (send RP-ERROR)
+     * @param ackPdu acknowledgement TPDU in hexadecimal format
+     *
+     * Response function is IRadioMessagingResponse.acknowledgeIncomingGsmSmsWithPduResponse()
+     */
+    void acknowledgeIncomingGsmSmsWithPdu(in int serial, in boolean success, in String ackPdu);
+
+    /**
+     * Acknowledge the success or failure in the receipt of SMS previously indicated
+     * via responseCdmaNewSms()
+     *
+     * @param serial Serial number of request.
+     * @param smsAck Cdma Sms ack to be sent described by CdmaSmsAck
+     *
+     * Response function is IRadioMessagingResponse.acknowledgeLastIncomingCdmaSmsResponse()
+     */
+    void acknowledgeLastIncomingCdmaSms(in int serial, in CdmaSmsAck smsAck);
+
+    /**
+     * Acknowledge successful or failed receipt of SMS previously indicated via unsolResponseNewSms
+     *
+     * @param serial Serial number of request.
+     * @param success is true on successful receipt
+     *        (basically, AT+CNMA=1 from TS 27.005 is 0 on failed receipt
+     *        (basically, AT+CNMA=2 from TS 27.005)
+     * @param cause: if success is false, this contains the failure cause as defined
+     *        in TS 23.040, 9.2.3.22.
+     *
+     * Response function is IRadioMessagingResponse.acknowledgeLastIncomingGsmSmsResponse()
+     */
+    void acknowledgeLastIncomingGsmSms(
+            in int serial, in boolean success, in SmsAcknowledgeFailCause cause);
+
+    /**
+     * Deletes a CDMA SMS message from RUIM memory.
+     *
+     * @param serial Serial number of request.
+     * @param index record index of the message to delete
+     *
+     * Response function is IRadioMessagingResponse.deleteSmsOnRuimResponse()
+     */
+    void deleteSmsOnRuim(in int serial, in int index);
+
+    /**
+     * Deletes a SMS message from SIM memory.
+     *
+     * @param serial Serial number of request.
+     * @param index Record index of the message to delete.
+     *
+     * Response function is IRadioMessagingResponse.deleteSmsOnSimResponse()
+     */
+    void deleteSmsOnSim(in int serial, in int index);
+
+    /**
+     * Request the setting of CDMA Broadcast SMS config
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioMessagingResponse.getCdmaBroadcastConfigResponse()
+     */
+    void getCdmaBroadcastConfig(in int serial);
+
+    /**
+     * Request the setting of GSM/WCDMA Cell Broadcast SMS config.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioMessagingResponse.getGsmBroadcastConfigResponse()
+     */
+    void getGsmBroadcastConfig(in int serial);
+
+    /**
+     * Get the default Short Message Service Center address on the device.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioMessagingResponse.getSmscAddressResponse()
+     */
+    void getSmscAddress(in int serial);
+
+    /**
+     * Indicates whether there is storage available for new SMS messages.
+     *
+     * @param serial Serial number of request.
+     * @param available true if memory is available for storing new messages,
+     *        false if memory capacity is exceeded
+     *
+     * Response function is IRadioMessagingResponse.reportSmsMemoryStatusResponse()
+     */
+    void reportSmsMemoryStatus(in int serial, in boolean available);
+
+    /**
+     * When response type received from a radio indication or radio response is
+     * RadioIndicationType:UNSOLICITED_ACK_EXP or RadioResponseType:SOLICITED_ACK_EXP respectively,
+     * acknowledge the receipt of those messages by sending responseAcknowledgement().
+     */
+    void responseAcknowledgement();
+
+    /**
+     * Send a CDMA SMS message
+     *
+     * @param serial Serial number of request.
+     * @param sms CdmaSmsMessage to be sent
+     *
+     * Response function is IRadioMessagingResponse.sendCdmaSmsResponse()
+     */
+    void sendCdmaSms(in int serial, in CdmaSmsMessage sms);
+
+    /**
+     * Send an SMS message. Identical to sendCdmaSms, except that more messages are expected to be
+     * sent soon.
+     *
+     * @param serial Serial number of request.
+     * @param sms CdmaSmsMessage to be sent
+     *
+     * Response function is IRadioMessagingResponse.sendCdmaSmsExpectMoreResponse()
+     */
+    void sendCdmaSmsExpectMore(in int serial, in CdmaSmsMessage sms);
+
+    /**
+     * Send a SMS message over IMS. Based on the return error, caller decides to resend if sending
+     * sms fails. SMS_SEND_FAIL_RETRY means retry, and other errors means no retry.
+     * In case of retry, data is encoded based on Voice Technology available.
+     *
+     * @param serial Serial number of request.
+     * @param message ImsSmsMessage to be sent
+     *
+     * Response function is IRadioMessagingResponse.sendImsSmsResponse()
+     */
+    void sendImsSms(in int serial, in ImsSmsMessage message);
+
+    /**
+     * Send an SMS message. Based on the returned error, caller decides to resend if sending sms
+     * fails. RadioError:SMS_SEND_FAIL_RETRY means retry (i.e. error cause is 332) and
+     * RadioError:GENERIC_FAILURE means no retry (i.e. error cause is 500)
+     *
+     * @param serial Serial number of request.
+     * @param message GsmSmsMessage to be sent
+     *
+     * Response function is IRadioMessagingResponse.sendSmsResponse()
+     */
+    void sendSms(in int serial, in GsmSmsMessage message);
+
+    /**
+     * Send an SMS message. Identical to sendSms, except that more messages are expected to be sent
+     * soon. If possible, keep SMS relay protocol link open (eg TS 27.005 AT+CMMS command).
+     * Based on the return error, caller decides to resend if sending sms fails.
+     * RadioError:SMS_SEND_FAIL_RETRY means retry (i.e. error cause is 332) and
+     * RadioError:GENERIC_FAILURE means no retry (i.e. error cause is 500)
+     *
+     * @param serial Serial number of request.
+     * @param message GsmSmsMessage to be sent
+     *
+     * Response function is IRadioMessagingResponse.sendSmsExpectMoreResponse()
+     */
+    void sendSmsExpectMore(in int serial, in GsmSmsMessage message);
+
+    /**
+     * Enable or disable the reception of CDMA Cell Broadcast SMS
+     *
+     * @param serial Serial number of request.
+     * @param activate indicates to activate or turn off the reception of CDMA Cell Broadcast SMS.
+     *        true = activate, false = turn off
+     *
+     * Response function is IRadioMessagingResponse.setCdmaBroadcastActivationResponse()
+     */
+    void setCdmaBroadcastActivation(in int serial, in boolean activate);
+
+    /**
+     * Set CDMA Broadcast SMS config
+     *
+     * @param serial Serial number of request.
+     * @param configInfo CDMA Broadcast SMS config to be set.
+     *
+     * Response function is IRadioMessagingResponse.setCdmaBroadcastConfigResponse()
+     */
+    void setCdmaBroadcastConfig(in int serial, in CdmaBroadcastSmsConfigInfo[] configInfo);
+
+    /**
+     * Enable or disable the reception of GSM/WCDMA Cell Broadcast SMS
+     *
+     * @param serial Serial number of request.
+     * @param activate indicates to activate or turn off the reception of GSM/WCDMA
+     *        Cell Broadcast SMS. true = activate, false = turn off
+     *
+     * Response function is IRadioMessagingResponse.setGsmBroadcastActivationResponse()
+     */
+    void setGsmBroadcastActivation(in int serial, in boolean activate);
+
+    /**
+     * Set GSM/WCDMA Cell Broadcast SMS config
+     *
+     * @param serial Serial number of request.
+     * @param configInfo Setting of GSM/WCDMA Cell broadcast config
+     *
+     * Response function is IRadioMessagingResponse.setGsmBroadcastConfigResponse()
+     */
+    void setGsmBroadcastConfig(in int serial, in GsmBroadcastSmsConfigInfo[] configInfo);
+
+    /**
+     * Set response functions for messaging radio requests and indications.
+     *
+     * @param radioMessagingResponse Object containing response functions
+     * @param radioMessagingIndication Object containing radio indications
+     */
+    void setResponseFunctions(in IRadioMessagingResponse radioMessagingResponse,
+            in IRadioMessagingIndication radioMessagingIndication);
+
+    /**
+     * Set the default Short Message Service Center address on the device.
+     *
+     * @param serial Serial number of request.
+     * @param smsc Short Message Service Center address to set
+     *
+     * Response function is IRadioMessagingResponse.setSmscAddressResponse()
+     */
+    void setSmscAddress(in int serial, in String smsc);
+
+    /**
+     * Stores a CDMA SMS message to RUIM memory.
+     *
+     * @param serial Serial number of request.
+     * @param cdmaSms CdmaSmsWriteArgs
+     *
+     * Response function is IRadioMessagingResponse.writeSmsToRuimResponse()
+     */
+    void writeSmsToRuim(in int serial, in CdmaSmsWriteArgs cdmaSms);
+
+    /**
+     * Stores a SMS message to SIM memory.
+     *
+     * @param serial Serial number of request.
+     * @param smsWriteArgs SmsWriteArgs
+     *
+     * Response function is IRadioMessagingResponse.writeSmsToSimResponse()
+     */
+    void writeSmsToSim(in int serial, in SmsWriteArgs smsWriteArgs);
+}
diff --git a/radio/aidl/android/hardware/radio/messaging/IRadioMessagingIndication.aidl b/radio/aidl/android/hardware/radio/messaging/IRadioMessagingIndication.aidl
new file mode 100644
index 0000000..8834cd9
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/messaging/IRadioMessagingIndication.aidl
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.messaging;
+
+import android.hardware.radio.RadioIndicationType;
+import android.hardware.radio.messaging.CdmaSmsMessage;
+
+/**
+ * Interface declaring unsolicited radio indications for messaging APIs.
+ */
+@VintfStability
+oneway interface IRadioMessagingIndication {
+    /**
+     * Indicates when new CDMA SMS is received. Callee must subsequently confirm the receipt of the
+     * SMS with acknowledgeLastIncomingCdmaSms(). Server must not send cdmaNewSms() messages until
+     * acknowledgeLastIncomingCdmaSms() has been received.
+     *
+     * @param type Type of radio indication
+     * @param msg Cdma Sms Message
+     */
+    void cdmaNewSms(in RadioIndicationType type, in CdmaSmsMessage msg);
+
+    /**
+     * Indicates that SMS storage on the RUIM is full. Messages cannot be saved on the RUIM until
+     * space is freed.
+     *
+     * @param type Type of radio indication
+     */
+    void cdmaRuimSmsStorageFull(in RadioIndicationType type);
+
+    /**
+     * Indicates when new Broadcast SMS is received
+     *
+     * @param type Type of radio indication
+     * @param data If received from GSM network, "data" is byte array of 88 bytes which indicates
+     *        each page of a CBS Message sent to the MS by the BTS as coded in 3GPP 23.041 Section
+     *        9.4.1.2. If received from UMTS network, "data" is byte array of 90 up to 1252 bytes
+     *        which contain between 1 and 15 CBS Message pages sent as one packet to the MS by the
+     *        BTS as coded in 3GPP 23.041 Section 9.4.2.2
+     */
+    void newBroadcastSms(in RadioIndicationType type, in byte[] data);
+
+    /**
+     * Indicates when new SMS is received. Callee must subsequently confirm the receipt of the SMS
+     * with a acknowledgeLastIncomingGsmSms(). Server must not send newSms() or newSmsStatusReport()
+     * messages until an acknowledgeLastIncomingGsmSms() has been received.
+     *
+     * @param type Type of radio indication
+     * @param pdu PDU of SMS-DELIVER represented as byte array.
+     *        The PDU starts with the SMSC address per TS 27.005 (+CMT:)
+     */
+    void newSms(in RadioIndicationType type, in byte[] pdu);
+
+    /**
+     * Indicates when new SMS has been stored on SIM card
+     *
+     * @param type Type of radio indication
+     * @param recordNumber Record number on the sim
+     */
+    void newSmsOnSim(in RadioIndicationType type, in int recordNumber);
+
+    /**
+     * Indicates when new SMS Status Report is received. Callee must subsequently confirm the
+     * receipt of the SMS with a acknowledgeLastIncomingGsmSms(). Server must not send newSms() or
+     * newSmsStatusReport() messages until an acknowledgeLastIncomingGsmSms() has been received
+     *
+     * @param type Type of radio indication
+     * @param pdu PDU of SMS-STATUS-REPORT represented as byte array.
+     *        The PDU starts with the SMSC address per TS 27.005 (+CMT:)
+     */
+    void newSmsStatusReport(in RadioIndicationType type, in byte[] pdu);
+
+    /**
+     * Indicates that SMS storage on the SIM is full. Sent when the network attempts to deliver a
+     * new SMS message. Messages cannot be saved on the SIM until space is freed. In particular,
+     * incoming Class 2 messages must not be stored.
+     *
+     * @param type Type of radio indication
+     */
+    void simSmsStorageFull(in RadioIndicationType type);
+}
diff --git a/radio/aidl/android/hardware/radio/messaging/IRadioMessagingResponse.aidl b/radio/aidl/android/hardware/radio/messaging/IRadioMessagingResponse.aidl
new file mode 100644
index 0000000..492755f
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/messaging/IRadioMessagingResponse.aidl
@@ -0,0 +1,540 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.messaging;
+
+import android.hardware.radio.RadioResponseInfo;
+import android.hardware.radio.messaging.CdmaBroadcastSmsConfigInfo;
+import android.hardware.radio.messaging.GsmBroadcastSmsConfigInfo;
+import android.hardware.radio.messaging.SendSmsResult;
+
+/**
+ * Interface declaring response functions to solicited radio requests for messaging APIs.
+ */
+@VintfStability
+oneway interface IRadioMessagingResponse {
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void acknowledgeIncomingGsmSmsWithPduResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:NO_SMS_TO_ACK
+     *   RadioError:INVALID_STATE
+     *   RadioError:NO_MEMORY
+     *   RadioError:REQUEST_RATE_LIMITED
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:MODEM_ERR
+     *   RadioError:NETWORK_NOT_READY
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void acknowledgeLastIncomingCdmaSmsResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void acknowledgeLastIncomingGsmSmsResponse(in RadioResponseInfo info);
+
+    /**
+     * Acknowledge the receipt of radio request sent to the vendor. This must be sent only for
+     * radio request which take long time to respond. For more details, refer
+     * https://source.android.com/devices/tech/connect/ril.html
+     *
+     * @param serial Serial no. of the request whose acknowledgement is sent.
+     */
+    void acknowledgeRequest(in int serial);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:NO_MEMORY
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:MODEM_ERR
+     *   RadioError:NO_SUCH_ENTRY
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:SIM_ABSENT
+     */
+    void deleteSmsOnRuimResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:SIM_FULL
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:NO_MEMORY
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:MODEM_ERR
+     *   RadioError:NO_SUCH_ENTRY
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:SIM_ABSENT
+     */
+    void deleteSmsOnSimResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param configs Vector of CDMA Broadcast SMS configs.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_STATE
+     *   RadioError:NO_MEMORY
+     *   RadioError:REQUEST_RATE_LIMITED
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:MODEM_ERR
+     *   RadioError:NO_RESOURCES
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:INVALID_MODEM_STATE
+     */
+    void getCdmaBroadcastConfigResponse(
+            in RadioResponseInfo info, in CdmaBroadcastSmsConfigInfo[] configs);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param configs Vector of GSM/WCDMA Cell broadcast configs
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_STATE
+     *   RadioError:NO_MEMORY
+     *   RadioError:REQUEST_RATE_LIMITED
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:MODEM_ERR
+     *   RadioError:NO_RESOURCES
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:INVALID_MODEM_STATE
+     */
+    void getGsmBroadcastConfigResponse(
+            in RadioResponseInfo info, in GsmBroadcastSmsConfigInfo[] configs);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param smsc Short Message Service Center address on the device
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:REQUEST_RATE_LIMITED
+     *   RadioError:MODEM_ERR
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:NOT_PROVISIONED
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:SIM_ABSENT
+     */
+    void getSmscAddressResponse(in RadioResponseInfo info, in String smsc);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:NO_MEMORY
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:REQUEST_RATE_LIMITED
+     *   RadioError:MODEM_ERR
+     *   RadioError:INVALID_STATE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:SIM_ABSENT
+     */
+    void reportSmsMemoryStatusResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param sms Response to sms sent as defined by SendSmsResult
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:SMS_SEND_FAIL_RETRY
+     *   RadioError:NETWORK_REJECT
+     *   RadioError:INVALID_STATE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:NO_MEMORY
+     *   RadioError:REQUEST_RATE_LIMITED
+     *   RadioError:INVALID_SMS_FORMAT
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:FDN_CHECK_FAILURE
+     *   RadioError:ENCODING_ERR
+     *   RadioError:INVALID_SMSC_ADDRESS
+     *   RadioError:MODEM_ERR
+     *   RadioError:NETWORK_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:NETWORK_NOT_READY
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:SIM_ABSENT
+     *   RadioError:SIMULTANEOUS_SMS_AND_CALL_NOT_ALLOWED
+     *   RadioError:ACCESS_BARRED
+     *   RadioError:BLOCKED_DUE_TO_CALL
+     */
+    void sendCdmaSmsExpectMoreResponse(in RadioResponseInfo info, in SendSmsResult sms);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param sms Sms result struct as defined by SendSmsResult
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:SMS_SEND_FAIL_RETRY
+     *   RadioError:NETWORK_REJECT
+     *   RadioError:INVALID_STATE
+     *   RadioError:NO_MEMORY
+     *   RadioError:REQUEST_RATE_LIMITED
+     *   RadioError:INVALID_SMS_FORMAT
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:FDN_CHECK_FAILURE
+     *   RadioError:MODEM_ERR
+     *   RadioError:NETWORK_ERR
+     *   RadioError:ENCODING_ERR
+     *   RadioError:INVALID_SMSC_ADDRESS
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:ENCODING_ERR
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:SIM_ABSENT
+     *   RadioError:SIMULTANEOUS_SMS_AND_CALL_NOT_ALLOWED
+     *   RadioError:ACCESS_BARRED
+     *   RadioError:BLOCKED_DUE_TO_CALL
+     */
+    void sendCdmaSmsResponse(in RadioResponseInfo info, in SendSmsResult sms);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param sms Response to sms sent as defined by SendSmsResult
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:SMS_SEND_FAIL_RETRY
+     *   RadioError:FDN_CHECK_FAILURE
+     *   RadioError:NETWORK_REJECT
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_STATE
+     *   RadioError:NO_MEMORY
+     *   RadioError:INVALID_SMS_FORMAT
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:REQUEST_RATE_LIMITED
+     *   RadioError:MODEM_ERR
+     *   RadioError:NETWORK_ERR
+     *   RadioError:ENCODING_ERR
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NETWORK_NOT_READY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void sendImsSmsResponse(in RadioResponseInfo info, in SendSmsResult sms);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param sms Response to sms sent as defined by SendSmsResult
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:SMS_SEND_FAIL_RETRY
+     *   RadioError:NETWORK_REJECT
+     *   RadioError:INVALID_STATE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:NO_MEMORY
+     *   RadioError:REQUEST_RATE_LIMITED
+     *   RadioError:INVALID_SMS_FORMAT
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:FDN_CHECK_FAILURE
+     *   RadioError:ENCODING_ERR
+     *   RadioError:INVALID_SMSC_ADDRESS
+     *   RadioError:MODEM_ERR
+     *   RadioError:NETWORK_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:NETWORK_NOT_READY
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:SIM_ABSENT
+     *   RadioError:ACCESS_BARRED
+     *   RadioError:BLOCKED_DUE_TO_CALL
+     */
+    void sendSmsExpectMoreResponse(in RadioResponseInfo info, in SendSmsResult sms);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param sms Response to sms sent as defined by SendSmsResult
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:SMS_SEND_FAIL_RETRY
+     *   RadioError:NETWORK_REJECT
+     *   RadioError:INVALID_STATE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:NO_MEMORY
+     *   RadioError:REQUEST_RATE_LIMITED
+     *   RadioError:INVALID_SMS_FORMAT
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:ENCODING_ERR
+     *   RadioError:INVALID_SMSC_ADDRESS
+     *   RadioError:MODEM_ERR
+     *   RadioError:NETWORK_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:NETWORK_NOT_READY
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:SIM_ABSENT
+     *   RadioError:ACCESS_BARRED
+     *   RadioError:BLOCKED_DUE_TO_CALL
+     */
+    void sendSmsResponse(in RadioResponseInfo info, in SendSmsResult sms);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_STATE
+     *   RadioError:NO_MEMORY
+     *   RadioError:REQUEST_RATE_LIMITED
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:INVALID_MODEM_STATE
+     */
+    void setCdmaBroadcastActivationResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_STATE
+     *   RadioError:NO_MEMORY
+     *   RadioError:REQUEST_RATE_LIMITED
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:INVALID_MODEM_STATE
+     */
+    void setCdmaBroadcastConfigResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_STATE
+     *   RadioError:NO_MEMORY
+     *   RadioError:REQUEST_RATE_LIMITED
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:INVALID_MODEM_STATE
+     */
+    void setGsmBroadcastActivationResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_STATE
+     *   RadioError:NO_MEMORY
+     *   RadioError:REQUEST_RATE_LIMITED
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:INVALID_MODEM_STATE
+     */
+    void setGsmBroadcastConfigResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_SMS_FORMAT
+     *   RadioError:NO_MEMORY
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:REQUEST_RATE_LIMITED
+     *   RadioError:MODEM_ERR
+     *   RadioError:NO_RESOURCES
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:SIM_ABSENT
+     */
+    void setSmscAddressResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param index record index where the cmda sms message is stored
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_SMS_FORMAT
+     *   RadioError:SIM_FULL
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:MODEM_ERR
+     *   RadioError:ENCODING_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:INVALID_SMSC_ADDRESS
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:SIM_ABSENT
+     */
+    void writeSmsToRuimResponse(in RadioResponseInfo info, in int index);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param index record index where the message is stored
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:SIM_FULL
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_SMS_FORMAT
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:MODEM_ERR
+     *   RadioError:ENCODING_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:INVALID_SMSC_ADDRESS
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:CANCELLED
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:SIM_ABSENT
+     */
+    void writeSmsToSimResponse(in RadioResponseInfo info, in int index);
+}
diff --git a/radio/aidl/android/hardware/radio/messaging/ImsSmsMessage.aidl b/radio/aidl/android/hardware/radio/messaging/ImsSmsMessage.aidl
new file mode 100644
index 0000000..d4be044
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/messaging/ImsSmsMessage.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.messaging;
+
+import android.hardware.radio.RadioTechnologyFamily;
+import android.hardware.radio.messaging.CdmaSmsMessage;
+import android.hardware.radio.messaging.GsmSmsMessage;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable ImsSmsMessage {
+    RadioTechnologyFamily tech;
+    /**
+     * Retry if true
+     */
+    boolean retry;
+    /**
+     * Valid field if retry is set to true.
+     * Contains messageRef from SendSmsResult struct corresponding to failed MO SMS.
+     */
+    int messageRef;
+    /**
+     * Valid field if tech is 3GPP2 and size = 1 else must be empty. Only one of cdmaMessage and
+     * gsmMessage must be of size 1 based on the RadioTechnologyFamily and the other must be size 0.
+     */
+    CdmaSmsMessage[] cdmaMessage;
+    /**
+     * Valid field if tech is 3GPP and size = 1 else must be empty. Only one of cdmaMessage and
+     * gsmMessage must be of size 1 based on the RadioTechnologyFamily and the other must be size 0.
+     */
+    GsmSmsMessage[] gsmMessage;
+}
diff --git a/radio/aidl/android/hardware/radio/messaging/SendSmsResult.aidl b/radio/aidl/android/hardware/radio/messaging/SendSmsResult.aidl
new file mode 100644
index 0000000..80e059c
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/messaging/SendSmsResult.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.messaging;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable SendSmsResult {
+    /**
+     * TP-Message-Reference for GSM, and BearerData MessageId for CDMA.
+     * See 3GPP2 C.S0015-B, v2.0, table 4.5-1
+     */
+    int messageRef;
+    /**
+     * Ack PDU or empty string if n/a
+     */
+    String ackPDU;
+    /**
+     * See 3GPP 27.005, 3.2.5 for GSM/UMTS, 3GPP2 N.S0005 (IS-41C) Table 171 for CDMA.
+     * -1 if unknown or not applicable.
+     */
+    int errorCode;
+}
diff --git a/radio/aidl/android/hardware/radio/messaging/SmsAcknowledgeFailCause.aidl b/radio/aidl/android/hardware/radio/messaging/SmsAcknowledgeFailCause.aidl
new file mode 100644
index 0000000..eb15bf1
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/messaging/SmsAcknowledgeFailCause.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.messaging;
+
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum SmsAcknowledgeFailCause {
+    MEMORY_CAPACITY_EXCEEDED = 0xD3,
+    UNSPECIFIED_ERROR = 0XFF,
+}
diff --git a/radio/aidl/android/hardware/radio/messaging/SmsWriteArgs.aidl b/radio/aidl/android/hardware/radio/messaging/SmsWriteArgs.aidl
new file mode 100644
index 0000000..6eef941
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/messaging/SmsWriteArgs.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.messaging;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable SmsWriteArgs {
+    const int STATUS_REC_UNREAD = 0;
+    const int STATUS_REC_READ = 1;
+    const int STATUS_STO_UNSENT = 2;
+    const int STATUS_STO_SENT = 3;
+
+    /**
+     * Status of message. See TS 27.005 3.1.
+     * Values are STATUS_
+     */
+    int status;
+    /**
+     * PDU of message to write, as an ASCII hex string less the SMSC address, the TP-layer length
+     * is strlen(pdu)/2.
+     */
+    String pdu;
+    /**
+     * SMSC address in GSM BCD format prefixed by a length byte (as expected by TS 27.005)
+     * or NULL for default SMSC.
+     */
+    String smsc;
+}
diff --git a/radio/aidl/android/hardware/radio/modem/ActivityStatsInfo.aidl b/radio/aidl/android/hardware/radio/modem/ActivityStatsInfo.aidl
new file mode 100644
index 0000000..b2a56d4
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/modem/ActivityStatsInfo.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.modem;
+
+import android.hardware.radio.modem.ActivityStatsTechSpecificInfo;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable ActivityStatsInfo {
+    /**
+     * Total time (in ms) when modem is in a low power or sleep state
+     */
+    int sleepModeTimeMs;
+    /**
+     * Total time (in ms) when modem is awake but neither the transmitter nor receiver are
+     * active/awake
+     */
+    int idleModeTimeMs;
+    /**
+     * Technology specific activity stats info.
+     * List of the activity stats for each RATs (2G, 3G, 4G and 5G) and frequency ranges (HIGH for
+     * sub6 and MMWAVE) in case of 5G. In case implementation doesn't have RAT specific activity
+     * stats then send only one activity stats info with RAT unknown.
+     */
+    ActivityStatsTechSpecificInfo[] techSpecificInfo;
+}
diff --git a/radio/aidl/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.aidl b/radio/aidl/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.aidl
new file mode 100644
index 0000000..fcc2df2
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.aidl
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.modem;
+
+import android.hardware.radio.AccessNetwork;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable ActivityStatsTechSpecificInfo {
+    /** Indicates the frequency range is unknown. */
+    const int FREQUENCY_RANGE_UNKNOWN = 0;
+    /** Indicates the frequency range is below 1GHz. */
+    const int FREQUENCY_RANGE_LOW = 1;
+    /** Indicates the frequency range is between 1GHz and 3GHz. */
+    const int FREQUENCY_RANGE_MID = 2;
+    /** Indicates the frequency range is between 3GHz and 6GHz. */
+    const int FREQUENCY_RANGE_HIGH = 3;
+    /** Indicates the frequency range is above 6GHz (millimeter wave frequency). */
+    const int FREQUENCY_RANGE_MMWAVE = 4;
+    /**
+     * Radio access technology. Set UNKNOWN if the Activity statistics
+     * is RAT independent.
+     */
+    AccessNetwork rat;
+    /**
+     * Frequency range. Values are FREQUENCY_RANGE_
+     * Set FREQUENCY_RANGE_UNKNOWN if the Activity statistics when frequency range
+     * is not applicable.
+     */
+    int frequencyRange;
+    /**
+     * Each index represent total time (in ms) during which the transmitter is active/awake for a
+     * particular power range as shown below.
+     * index 0 = tx_power <= 0dBm
+     * index 1 = 0dBm < tx_power <= 5dBm
+     * index 2 = 5dBm < tx_power <= 15dBm
+     * index 3 = 15dBm < tx_power <= 20dBm
+     * index 4 = tx_power > 20dBm
+     */
+    int[] txmModetimeMs;
+    /**
+     * Total time (in ms) for which receiver is active/awake and the transmitter is inactive
+     */
+    int rxModeTimeMs;
+}
diff --git a/radio/aidl/android/hardware/radio/modem/DeviceStateType.aidl b/radio/aidl/android/hardware/radio/modem/DeviceStateType.aidl
new file mode 100644
index 0000000..ad0d59c
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/modem/DeviceStateType.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.modem;
+
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum DeviceStateType {
+    /**
+     * Device power save mode (provided by PowerManager). True indicates the device is in
+     * power save mode.
+     */
+    POWER_SAVE_MODE,
+    /**
+     * Device charging state (provided by BatteryManager). True indicates the device is charging.
+     */
+    CHARGING_STATE,
+    /**
+     * Low data expected mode. True indicates low data traffic is expected, for example, when the
+     * device is idle (e.g. not doing tethering in the background). Note this doesn't mean no data
+     * is expected.
+     */
+    LOW_DATA_EXPECTED,
+}
diff --git a/radio/aidl/android/hardware/radio/modem/HardwareConfig.aidl b/radio/aidl/android/hardware/radio/modem/HardwareConfig.aidl
new file mode 100644
index 0000000..8eb1f2d
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/modem/HardwareConfig.aidl
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.modem;
+
+import android.hardware.radio.modem.HardwareConfigModem;
+import android.hardware.radio.modem.HardwareConfigSim;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable HardwareConfig {
+    const int STATE_ENABLED = 0;
+    const int STATE_STANDBY = 1;
+    const int STATE_DISABLED = 2;
+
+    const int TYPE_MODEM = 0;
+    const int TYPE_SIM = 1;
+
+    /**
+     * Values are TYPE_
+     */
+    int type;
+    /**
+     * RadioConst:MAX_UUID_LENGTH is max length of the string
+     */
+    String uuid;
+    /**
+     * Values are STATE_
+     */
+    int state;
+    /**
+     * Valid only if type is Modem and size = 1 else must be empty. Only one of modem or sim must
+     * have size = 1 based on the HardwareConfigType, and the other must have size = 0.
+     */
+    HardwareConfigModem[] modem;
+    /**
+     * Valid only if type is SIM and size = 1 else must be empty. Only one of modem or sim must
+     * have size = 1 based on the HardwareConfigType, and the other must have size = 0.
+     */
+    HardwareConfigSim[] sim;
+}
diff --git a/radio/aidl/android/hardware/radio/modem/HardwareConfigModem.aidl b/radio/aidl/android/hardware/radio/modem/HardwareConfigModem.aidl
new file mode 100644
index 0000000..f5e2c27
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/modem/HardwareConfigModem.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.modem;
+
+import android.hardware.radio.RadioTechnology;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable HardwareConfigModem {
+    /**
+     * RIL attachment model. Values are:
+     * 0: single
+     * 1: multiple
+     * If single, there is a one-to-one relationship between a modem hardware and a ril daemon.
+     * If multiple, there is a one-to-many relationship between a modem hardware and several
+     * simultaneous ril daemons.
+     */
+    int rilModel;
+    /**
+     * Bitset value, based on RadioTechnology.
+     */
+    RadioTechnology rat;
+    /**
+     * Maximum number of concurrent active voice calls.
+     */
+    int maxVoiceCalls;
+    /**
+     * Maximum number of concurrent active data calls.
+     */
+    int maxDataCalls;
+    /**
+     * Maximum number of concurrent standby connections. This is not necessarily an equal sum of the
+     * maxVoice and maxData (or a derivative of it) since it really depends on the modem capability,
+     * hence it is left for the hardware to define.
+     */
+    int maxStandby;
+}
diff --git a/radio/aidl/android/hardware/radio/modem/HardwareConfigSim.aidl b/radio/aidl/android/hardware/radio/modem/HardwareConfigSim.aidl
new file mode 100644
index 0000000..c82bc6e
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/modem/HardwareConfigSim.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.modem;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable HardwareConfigSim {
+    /**
+     * RadioConst:MAX_UUID_LENGTH is max length of the string
+     */
+    String modemUuid;
+}
diff --git a/radio/aidl/android/hardware/radio/modem/IRadioModem.aidl b/radio/aidl/android/hardware/radio/modem/IRadioModem.aidl
new file mode 100644
index 0000000..ba0ddb9
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/modem/IRadioModem.aidl
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.modem;
+
+import android.hardware.radio.modem.DeviceStateType;
+import android.hardware.radio.modem.IRadioModemIndication;
+import android.hardware.radio.modem.IRadioModemResponse;
+import android.hardware.radio.modem.NvItem;
+import android.hardware.radio.modem.NvWriteItem;
+import android.hardware.radio.modem.RadioCapability;
+import android.hardware.radio.modem.ResetNvType;
+
+/**
+ * This interface is used by telephony and telecom to talk to cellular radio for modem APIs.
+ * All the functions have minimum one parameter:
+ * serial: which corresponds to serial no. of request. Serial numbers must only be memorized for the
+ * duration of a method call. If clients provide colliding serials (including passing the same
+ * serial to different methods), multiple responses (one for each method call) must still be served.
+ * setResponseFunctions must work with IRadioModemResponse and IRadioModemIndication.
+ */
+@VintfStability
+oneway interface IRadioModem {
+    /**
+     * Toggle logical modem on/off. This is similar to IRadioModem.setRadioPower(), however that
+     * does not enforce that radio power is toggled only for the corresponding radio and certain
+     * vendor implementations do it for all radios. This new API should affect only the modem for
+     * which it is called. A modem stack must be on/active only when both setRadioPower() and
+     * enableModem() are set to on for it.
+     *
+     * SIM must be read if available even if modem is off/inactive.
+     *
+     * @param serial Serial number of request.
+     * @param on True to turn on the logical modem, otherwise turn it off.
+     *
+     * Response function is IRadioModemResponse.enableModemResponse()
+     */
+    void enableModem(in int serial, in boolean on);
+
+    /**
+     * Return string value indicating baseband version, eg response from AT+CGMR
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioModemResponse.getBasebandVersionResponse()
+     */
+    void getBasebandVersion(in int serial);
+
+    /**
+     * Request the device ESN / MEID / IMEI / IMEISV. The request is always allowed and contains
+     * GSM and CDMA device identity. When CDMA subscription is changed the ESN/MEID changes.
+     * The application layer must re-issue the request to update the device identity in this case.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioModemResponse.getDeviceIdentityResponse()
+     */
+    void getDeviceIdentity(in int serial);
+
+    /**
+     * Request all of the current hardware (modem and sim) associated with Radio.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioModemResponse.getHardwareConfigResponse()
+     */
+    void getHardwareConfig(in int serial);
+
+    /**
+     * Get modem activity information for power consumption estimation. Request clear-on-read
+     * statistics information that is used for estimating the per-millisecond power consumption
+     * of the cellular modem.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioModemResponse.getModemActivityInfoResponse()
+     */
+    void getModemActivityInfo(in int serial);
+
+    /**
+     * Request status of logical modem. It returns isEnabled=true if the logical modem is on.
+     * This method is the getter method for enableModem.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioModemResponse.getModemStackStatusResponse()
+     */
+    void getModemStackStatus(in int serial);
+
+    /**
+     * Get phone radio capability.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioModemResponse.getRadioCapabilityResponse()
+     */
+    void getRadioCapability(in int serial);
+
+    /**
+     * Read one of the radio NV items.
+     * This is used for device configuration by some CDMA operators.
+     *
+     * @param serial Serial number of request.
+     * @param itemId NvItem
+     *
+     * Response function is IRadioModemResponse.nvReadItemResponse()
+     */
+    void nvReadItem(in int serial, in NvItem itemId);
+
+    /**
+     * Reset the radio NV configuration to the factory state.
+     * This is used for device configuration by some CDMA operators.
+     *
+     * @param serial Serial number of request.
+     * @param resetType ResetNvType
+     *
+     * Response function is IRadioModemResponse.nvResetConfigResponse()
+     */
+    void nvResetConfig(in int serial, in ResetNvType resetType);
+
+    /**
+     * Update the CDMA Preferred Roaming List (PRL) in the radio NV storage.
+     * This is used for device configuration by some CDMA operators.
+     *
+     * @param serial Serial number of request.
+     * @param prl PRL as a byte array
+     *
+     * Response function is IRadioModemResponse.nvWriteCdmaPrlResponse()
+     */
+    void nvWriteCdmaPrl(in int serial, in byte[] prl);
+
+    /**
+     * Write one of the radio NV items.
+     * This is used for device configuration by some CDMA operators.
+     *
+     * @param serial Serial number of request.
+     * @param item NvWriteItem
+     *
+     * Response function is IRadioModemResponse.nvWriteItemResponse()
+     */
+    void nvWriteItem(in int serial, in NvWriteItem item);
+
+    /**
+     * Device is shutting down. All further commands are ignored and RADIO_NOT_AVAILABLE
+     * must be returned.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioModemResponse.requestShutdownResponse()
+     */
+    void requestShutdown(in int serial);
+
+    /**
+     * When response type received from a radio indication or radio response is
+     * RadioIndicationType:UNSOLICITED_ACK_EXP or RadioResponseType:SOLICITED_ACK_EXP respectively,
+     * acknowledge the receipt of those messages by sending responseAcknowledgement().
+     */
+    void responseAcknowledgement();
+
+    /**
+     * Send the updated device state. This is providing the device state information for the modem
+     * to perform power saving strategies.
+     *
+     * @param serial Serial number of request.
+     * @param deviceStateType The updated device state type.
+     * @param state The updated state. See the definition of state at DeviceStateType.
+     *
+     * Response function is IRadioModemResponse.sendDeviceStateResponse()
+     */
+    void sendDeviceState(in int serial, in DeviceStateType deviceStateType, in boolean state);
+
+    /**
+     * Used to set the phones radio capability. Be VERY careful using this request as it may cause
+     * some vendor modems to reset. Because of the possible modem reset any radio commands after
+     * this one may not be processed.
+     *
+     * @param serial Serial number of request.
+     * @param rc RadioCapability structure to be set
+     *
+     * Response function is IRadioModemResponse.setRadioCapabilityResponse()
+     */
+    void setRadioCapability(in int serial, in RadioCapability rc);
+
+    /**
+     * Toggle radio on and off (for "airplane" mode). If the radio is turned off/on the radio modem
+     * subsystem is expected return to an initialized state. For instance, any voice and data calls
+     * must be terminated and all associated lists emptied.
+     * When setting radio power on to exit from airplane mode to place an emergency call on this
+     * logical modem, powerOn, forEmergencyCall and preferredForEmergencyCall must be true. In
+     * this case, this modem is optimized to scan only emergency call bands, until:
+     * 1) Emergency call is completed; or
+     * 2) Another setRadioPower is issued with forEmergencyCall being false or
+     *    preferredForEmergencyCall being false; or
+     * 3) Timeout after 30 seconds if dial or emergencyDial is not called.
+     * Once one of these conditions is reached, the modem should move into normal operation.
+     *
+     * @param serial Serial number of request.
+     * @param powerOn To turn on radio -> on = true, to turn off radio -> on = false.
+     * @param forEmergencyCall To indication to radio if this request is due to emergency call.
+     *        No effect if powerOn is false.
+     * @param preferredForEmergencyCall indicate whether the following emergency call will be sent
+     *        on this modem or not. No effect if forEmergencyCall is false, or powerOn is false.
+     *
+     * Response function is IRadioConfigResponse.setRadioPowerResponse()
+     */
+    void setRadioPower(in int serial, in boolean powerOn, in boolean forEmergencyCall,
+            in boolean preferredForEmergencyCall);
+
+    /**
+     * Set response functions for modem radio requests and indications.
+     *
+     * @param radioModemResponse Object containing response functions
+     * @param radioModemIndication Object containing radio indications
+     */
+    void setResponseFunctions(in IRadioModemResponse radioModemResponse,
+            in IRadioModemIndication radioModemIndication);
+}
diff --git a/radio/aidl/android/hardware/radio/modem/IRadioModemIndication.aidl b/radio/aidl/android/hardware/radio/modem/IRadioModemIndication.aidl
new file mode 100644
index 0000000..c61de99
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/modem/IRadioModemIndication.aidl
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.modem;
+
+import android.hardware.radio.RadioIndicationType;
+import android.hardware.radio.modem.HardwareConfig;
+import android.hardware.radio.modem.RadioCapability;
+import android.hardware.radio.modem.RadioState;
+
+/**
+ * Interface declaring unsolicited radio indications for modem APIs.
+ */
+@VintfStability
+oneway interface IRadioModemIndication {
+    /**
+     * Indicates when the hardware configuration associated with the RILd changes.
+     *
+     * @param type Type of radio indication
+     * @param configs Array of hardware configs
+     */
+    void hardwareConfigChanged(in RadioIndicationType type, in HardwareConfig[] configs);
+
+    /**
+     * Indicates when there is a modem reset.
+     * When modem restarts, one of the following radio state transitions must happen
+     * 1) RadioState:ON->RadioState:UNAVAILABLE->RadioState:ON or
+     * 2) RadioState:OFF->RadioState:UNAVAILABLE->RadioState:OFF
+     * This message must be sent either just before the Radio State changes to
+     * RadioState:UNAVAILABLE or just after but must never be sent after the Radio State changes
+     * from RadioState:UNAVAILABLE to RadioState:ON/RadioState:OFF again. It must NOT be sent after
+     * the Radio state changes to RadioState:ON/RadioState:OFF after the modem restart as that may
+     * be interpreted as a second modem reset by the framework.
+     *
+     * @param type Type of radio indication
+     * @param reason the reason for the reset. It may be a crash signature if the restart was due to
+     *        a crash or some string such as "user-initiated restart" or "AT command initiated
+     *        restart" that explains the cause of the modem restart
+     */
+    void modemReset(in RadioIndicationType type, in String reason);
+
+    /**
+     * Sent when setRadioCapability() completes. Returns the phone radio capability exactly as
+     * getRadioCapability() and must be the same set as sent by setRadioCapability().
+     *
+     * @param type Type of radio indication
+     * @param rc Current radio capability
+     */
+    void radioCapabilityIndication(in RadioIndicationType type, in RadioCapability rc);
+
+    /**
+     * Indicates when radio state changes.
+     *
+     * @param type Type of radio indication
+     * @param radioState Current radio state
+     */
+    void radioStateChanged(in RadioIndicationType type, in RadioState radioState);
+
+    /**
+     * Indicates the ril connects and returns the version
+     *
+     * @param type Type of radio indication
+     */
+    void rilConnected(in RadioIndicationType type);
+}
diff --git a/radio/aidl/android/hardware/radio/modem/IRadioModemResponse.aidl b/radio/aidl/android/hardware/radio/modem/IRadioModemResponse.aidl
new file mode 100644
index 0000000..b17cac4
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/modem/IRadioModemResponse.aidl
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.modem;
+
+import android.hardware.radio.RadioResponseInfo;
+import android.hardware.radio.modem.ActivityStatsInfo;
+import android.hardware.radio.modem.HardwareConfig;
+import android.hardware.radio.modem.RadioCapability;
+
+/**
+ * Interface declaring response functions to solicited radio requests for modem APIs.
+ */
+@VintfStability
+oneway interface IRadioModemResponse {
+    /**
+     * Acknowledge the receipt of radio request sent to the vendor. This must be sent only for
+     * radio request which take long time to respond. For more details, refer
+     * https://source.android.com/devices/tech/connect/ril.html
+     *
+     * @param serial Serial no. of the request whose acknowledgement is sent.
+     */
+    void acknowledgeRequest(in int serial);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:MODEM_ERR
+     *   RadioError:INVALID_STATE: this is for the case that the API is called in a single-sim
+     *              mode, or when there is only one modem available, as this API should only
+     *              be called in multi sim status.
+     */
+    void enableModemResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param version string containing version string for log reporting
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:EMPTY_RECORD
+     *   RadioError:NO_MEMORY
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:MODEM_ERR
+     *   RadioError:NOT_PROVISIONED
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void getBasebandVersionResponse(in RadioResponseInfo info, in String version);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param imei IMEI if GSM subscription is available
+     * @param imeisv IMEISV if GSM subscription is available
+     * @param esn ESN if CDMA subscription is available
+     * @param meid MEID if CDMA subscription is available
+     *
+     * If a empty string value is returned for any of the device id, it means that there was error
+     * accessing the device.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:NO_MEMORY
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:MODEM_ERR
+     *   RadioError:NOT_PROVISIONED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void getDeviceIdentityResponse(in RadioResponseInfo info, in String imei, in String imeisv,
+            in String esn, in String meid);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param config Array of HardwareConfig of the radio.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void getHardwareConfigResponse(in RadioResponseInfo info, in HardwareConfig[] config);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param activityInfo modem activity information
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:NO_MEMORY
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:MODEM_ERR
+     *   RadioError:NOT_PROVISIONED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void getModemActivityInfoResponse(in RadioResponseInfo info, in ActivityStatsInfo activityInfo);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:MODEM_ERR
+     */
+    void getModemStackStatusResponse(in RadioResponseInfo info, in boolean isEnabled);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param rc Radio capability as defined by RadioCapability in types.hal
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:INVALID_STATE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void getRadioCapabilityResponse(in RadioResponseInfo info, in RadioCapability rc);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param result string containing the contents of the NV item
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void nvReadItemResponse(in RadioResponseInfo info, in String result);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void nvResetConfigResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void nvWriteCdmaPrlResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void nvWriteItemResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:NO_MEMORY
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void requestShutdownResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:NO_MEMORY
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void sendDeviceStateResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param rc Radio capability as defined by RadioCapability in types.hal used to
+     *        feedback return status
+     *
+     * Valid errors returned:
+     *   RadioError:NONE means a unsol radioCapability() will be sent within 30 seconds.
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:NO_MEMORY
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:MODEM_ERR
+     *   RadioError:INVALID_STATE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void setRadioCapabilityResponse(in RadioResponseInfo info, in RadioCapability rc);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:RF_HARDWARE_ISSUE
+     *   RadioError:NO_RF_CALIBRATION_INFO
+     */
+    void setRadioPowerResponse(in RadioResponseInfo info);
+}
diff --git a/radio/aidl/android/hardware/radio/modem/NvItem.aidl b/radio/aidl/android/hardware/radio/modem/NvItem.aidl
new file mode 100644
index 0000000..649b0d2
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/modem/NvItem.aidl
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.modem;
+
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum NvItem {
+    /**
+     * CDMA radio and account information (items 1-10)
+     * CDMA MEID (hex)
+     */
+    CDMA_MEID = 1,
+    /**
+     * CDMA MIN (MSID)
+     */
+    CDMA_MIN = 2,
+    /**
+     * CDMA MDN
+     */
+    CDMA_MDN = 3,
+    /**
+     * CDMA access overload control
+     */
+    CDMA_ACCOLC = 4,
+    /**
+     * Carrier device provisioning (items 11-30)
+     * Device MSL
+     */
+    DEVICE_MSL = 11,
+    /**
+     * RTN reconditioned status
+     */
+    RTN_RECONDITIONED_STATUS = 12,
+    /**
+     * RTN activation date
+     */
+    RTN_ACTIVATION_DATE = 13,
+    /**
+     * RTN life timer
+     */
+    RTN_LIFE_TIMER = 14,
+    /**
+     * RTN life calls
+     */
+    RTN_LIFE_CALLS = 15,
+    /**
+     * RTN life data TX
+     */
+    RTN_LIFE_DATA_TX = 16,
+    /**
+     * RTN life data RX
+     */
+    RTN_LIFE_DATA_RX = 17,
+    /**
+     * HFA in progress
+     */
+    OMADM_HFA_LEVEL = 18,
+    /**
+     * Mobile IP profile information (items 31-50)
+     * NAI realm
+     */
+    MIP_PROFILE_NAI = 31,
+    /**
+     * MIP home address
+     */
+    MIP_PROFILE_HOME_ADDRESS = 32,
+    /**
+     * AAA auth
+     */
+    MIP_PROFILE_AAA_AUTH = 33,
+    /**
+     * HA auth
+     */
+    MIP_PROFILE_HA_AUTH = 34,
+    /**
+     * Primary HA address
+     */
+    MIP_PROFILE_PRI_HA_ADDR = 35,
+    /**
+     * Secondary HA address
+     */
+    MIP_PROFILE_SEC_HA_ADDR = 36,
+    /**
+     * Reverse TUN preference
+     */
+    MIP_PROFILE_REV_TUN_PREF = 37,
+    /**
+     * HA SPI
+     */
+    MIP_PROFILE_HA_SPI = 38,
+    /**
+     * AAA SPI
+     */
+    MIP_PROFILE_AAA_SPI = 39,
+    /**
+     * HA shared secret
+     */
+    MIP_PROFILE_MN_HA_SS = 40,
+    /**
+     * AAA shared secret
+     */
+    MIP_PROFILE_MN_AAA_SS = 41,
+    /**
+     * CDMA network and band config (items 51-70)
+     * CDMA PRL version
+     */
+    CDMA_PRL_VERSION = 51,
+    /**
+     * CDMA band class 10
+     */
+    CDMA_BC10 = 52,
+    /**
+     * CDMA band class 14
+     */
+    CDMA_BC14 = 53,
+    /**
+     * CDMA SO68
+     */
+    CDMA_SO68 = 54,
+    /**
+     * CDMA SO73 COP0
+     */
+    CDMA_SO73_COP0 = 55,
+    /**
+     * CDMA SO73 COP1-7
+     */
+    CDMA_SO73_COP1TO7 = 56,
+    /**
+     * CDMA 1X Advanced enabled
+     */
+    CDMA_1X_ADVANCED_ENABLED = 57,
+    /**
+     * CDMA eHRPD enabled
+     */
+    CDMA_EHRPD_ENABLED = 58,
+    /**
+     * CDMA eHRPD forced
+     */
+    CDMA_EHRPD_FORCED = 59,
+    /**
+     * LTE network and band config (items 71-90)
+     * LTE band 25 enabled
+     */
+    LTE_BAND_ENABLE_25 = 71,
+    /**
+     * LTE band 26 enabled
+     */
+    LTE_BAND_ENABLE_26 = 72,
+    /**
+     * LTE band 41 enabled
+     */
+    LTE_BAND_ENABLE_41 = 73,
+    /**
+     * LTE band 25 scan priority
+     */
+    LTE_SCAN_PRIORITY_25 = 74,
+    /**
+     * LTE band 26 scan priority
+     */
+    LTE_SCAN_PRIORITY_26 = 75,
+    /**
+     * LTE band 41 scan priority
+     */
+    LTE_SCAN_PRIORITY_41 = 76,
+    /**
+     * LTE hidden band 25 priority
+     */
+    LTE_HIDDEN_BAND_PRIORITY_25 = 77,
+    /**
+     * LTE hidden band 26 priority
+     */
+    LTE_HIDDEN_BAND_PRIORITY_26 = 78,
+    /**
+     * LTE hidden band 41 priority
+     */
+    LTE_HIDDEN_BAND_PRIORITY_41 = 79,
+}
diff --git a/radio/aidl/android/hardware/radio/modem/NvWriteItem.aidl b/radio/aidl/android/hardware/radio/modem/NvWriteItem.aidl
new file mode 100644
index 0000000..47fb490
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/modem/NvWriteItem.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.modem;
+
+import android.hardware.radio.modem.NvItem;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable NvWriteItem {
+    NvItem itemId;
+    String value;
+}
diff --git a/radio/aidl/android/hardware/radio/modem/RadioCapability.aidl b/radio/aidl/android/hardware/radio/modem/RadioCapability.aidl
new file mode 100644
index 0000000..16cba09
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/modem/RadioCapability.aidl
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.modem;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable RadioCapability {
+    /**
+     * Logical Modem's (LM) initial value and value after PHASE_FINISH completes.
+     */
+    const int PHASE_CONFIGURED = 0;
+    /**
+     * PHASE_START is sent before PHASE_APPLY and indicates that an APPLY is forthcoming with these
+     * same parameters.
+     */
+    const int PHASE_START = 1;
+    /**
+     * PHASE_APPLY is sent after all LM's receive PHASE_START and returned
+     * RadioCapability.status = 0.
+     * If any PHASE_START's fail, hal implementation must not send PHASE_APPLY.
+     */
+    const int PHASE_APPLY = 2;
+    /**
+     * PHASE_UNSOL_RSP is sent with unsolicited radioCapability().
+     */
+    const int PHASE_UNSOL_RSP = 3;
+    /**
+     * PHASE_FINISH is sent after all commands have completed. If an error occurs in any previous
+     * command, the RadioAccessFamily and logicalModemUuid fields must be the prior configuration
+     * thus restoring the configuration to the previous value. An error returned by PHASE_FINISH
+     * will generally be ignored or may cause that LM to be removed from service.
+     */
+    const int PHASE_FINISH = 4;
+
+    /**
+     * This parameter has no meaning with PHASE_START, PHASE_APPLY.
+     */
+    const int STATUS_NONE = 0;
+    /**
+     * Tell modem the action transaction of set radio capability was successful with PHASE_FINISH.
+     */
+    const int STATUS_SUCCESS = 1;
+    /**
+     * Tell modem the action transaction of set radio capability failed with PHASE_FINISH.
+     */
+    const int STATUS_FAIL = 2;
+
+    /**
+     * Unique session value defined by framework returned in all "responses/unslo".
+     */
+    int session;
+    /**
+     * Values are PHASE_
+     */
+    int phase;
+    /**
+     * 32-bit bitmap of RadioAccessFamily.
+     */
+    int raf;
+    /**
+     * A UUID typically "com.xxxx.lmX" where X is the logical modem.
+     * RadioConst:MAX_UUID_LENGTH is the max length.
+     */
+    String logicalModemUuid;
+    /**
+     * Values are STATUS_
+     */
+    int status;
+}
diff --git a/radio/aidl/android/hardware/radio/modem/RadioState.aidl b/radio/aidl/android/hardware/radio/modem/RadioState.aidl
new file mode 100644
index 0000000..dedad25
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/modem/RadioState.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.modem;
+
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum RadioState {
+    /**
+     * Radio explicitly powered off (eg CFUN=0)
+     */
+    OFF = 0,
+    /**
+     * Radio unavailable (eg, resetting or not booted)
+     */
+    UNAVAILABLE = 1,
+    /**
+     * Radio is on
+     */
+    ON = 10,
+}
diff --git a/radio/aidl/android/hardware/radio/modem/ResetNvType.aidl b/radio/aidl/android/hardware/radio/modem/ResetNvType.aidl
new file mode 100644
index 0000000..16487f8
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/modem/ResetNvType.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.modem;
+
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum ResetNvType {
+    /**
+     * Reload all NV items
+     */
+    RELOAD,
+    /**
+     * Erase NV reset (SCRTN)
+     */
+    ERASE,
+    /**
+     * Factory reset (RTN)
+     */
+    FACTORY_RESET,
+}
diff --git a/radio/aidl/android/hardware/radio/network/AccessTechnologySpecificInfo.aidl b/radio/aidl/android/hardware/radio/network/AccessTechnologySpecificInfo.aidl
new file mode 100644
index 0000000..8b95ced
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/AccessTechnologySpecificInfo.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+import android.hardware.radio.network.Cdma2000RegistrationInfo;
+import android.hardware.radio.network.EutranRegistrationInfo;
+import android.hardware.radio.network.NrVopsInfo;
+
+@VintfStability
+@JavaDerive(toString=true)
+union AccessTechnologySpecificInfo {
+    boolean noinit;
+    Cdma2000RegistrationInfo cdmaInfo;
+    EutranRegistrationInfo eutranInfo;
+    /**
+     * Network capabilities for voice over PS services. This info is valid only on NR network and
+     * must be present when the device is camped on NR. NrVopsInfo must be empty when the device is
+     * not camped on NR.
+     */
+    NrVopsInfo ngranNrVopsInfo;
+    /**
+     * True if the dual transfer mode is supported. Refer to 3GPP TS 44.108 section 3.4.25.3
+     */
+    boolean geranDtmSupported;
+}
diff --git a/radio/aidl/android/hardware/radio/network/BarringInfo.aidl b/radio/aidl/android/hardware/radio/network/BarringInfo.aidl
new file mode 100644
index 0000000..2759406
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/BarringInfo.aidl
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+import android.hardware.radio.network.BarringTypeSpecificInfo;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable BarringInfo {
+    /**
+     * Device is not barred for the given service
+     */
+    const int BARRING_TYPE_NONE = 0;
+    /**
+     * Device may be barred based on time and probability factors
+     */
+    const int BARRING_TYPE_CONDITIONAL = 1;
+    /*
+     * Device is unconditionally barred
+     */
+    const int BARRING_TYPE_UNCONDITIONAL = 2;
+
+    /**
+     * Applicable to UTRAN
+     * Barring for all CS services, including registration
+     */
+    const int SERVICE_TYPE_CS_SERVICE = 0;
+    /**
+     * Barring for all PS services, including registration
+     */
+    const int SERVICE_TYPE_PS_SERVICE = 1;
+    /**
+     * Barring for mobile-originated circuit-switched voice calls
+     */
+    const int SERVICE_TYPE_CS_VOICE = 2;
+    /**
+     * Applicable to EUTRAN, NGRAN
+     * Barring for mobile-originated signalling for any purpose
+     */
+    const int SERVICE_TYPE_MO_SIGNALLING = 3;
+    /**
+     * Barring for mobile-originated internet or other interactive data
+     */
+    const int SERVICE_TYPE_MO_DATA = 4;
+    /**
+     * Barring for circuit-switched fallback calling
+     */
+    const int SERVICE_TYPE_CS_FALLBACK = 5;
+    /**
+     * Barring for IMS voice calling
+     */
+    const int SERVICE_TYPE_MMTEL_VOICE = 6;
+    /**
+     * Barring for IMS video calling
+     */
+    const int SERVICE_TYPE_MMTEL_VIDEO = 7;
+    /**
+     * Applicable to UTRAN, EUTRAN, NGRAN
+     * Barring for emergency services, either CS or emergency MMTEL
+     */
+    const int SERVICE_TYPE_EMERGENCY = 8;
+    /**
+     * Barring for short message services
+     */
+    const int SERVICE_TYPE_SMS = 9;
+    /**
+     * Operator-specific barring codes; applicable to NGRAN
+     */
+    const int SERVICE_TYPE_OPERATOR_1 = 1001;
+    const int SERVICE_TYPE_OPERATOR_2 = 1002;
+    const int SERVICE_TYPE_OPERATOR_3 = 1003;
+    const int SERVICE_TYPE_OPERATOR_4 = 1004;
+    const int SERVICE_TYPE_OPERATOR_5 = 1005;
+    const int SERVICE_TYPE_OPERATOR_6 = 1006;
+    const int SERVICE_TYPE_OPERATOR_7 = 1007;
+    const int SERVICE_TYPE_OPERATOR_8 = 1008;
+    const int SERVICE_TYPE_OPERATOR_9 = 1009;
+    const int SERVICE_TYPE_OPERATOR_10 = 1010;
+    const int SERVICE_TYPE_OPERATOR_11 = 1011;
+    const int SERVICE_TYPE_OPERATOR_12 = 1012;
+    const int SERVICE_TYPE_OPERATOR_13 = 1013;
+    const int SERVICE_TYPE_OPERATOR_14 = 1014;
+    const int SERVICE_TYPE_OPERATOR_15 = 1015;
+    const int SERVICE_TYPE_OPERATOR_16 = 1016;
+    const int SERVICE_TYPE_OPERATOR_17 = 1017;
+    const int SERVICE_TYPE_OPERATOR_18 = 1018;
+    const int SERVICE_TYPE_OPERATOR_19 = 1019;
+    const int SERVICE_TYPE_OPERATOR_20 = 1020;
+    const int SERVICE_TYPE_OPERATOR_21 = 1021;
+    const int SERVICE_TYPE_OPERATOR_22 = 1022;
+    const int SERVICE_TYPE_OPERATOR_23 = 1023;
+    const int SERVICE_TYPE_OPERATOR_24 = 1024;
+    const int SERVICE_TYPE_OPERATOR_25 = 1025;
+    const int SERVICE_TYPE_OPERATOR_26 = 1026;
+    const int SERVICE_TYPE_OPERATOR_27 = 1027;
+    const int SERVICE_TYPE_OPERATOR_28 = 1028;
+    const int SERVICE_TYPE_OPERATOR_29 = 1029;
+    const int SERVICE_TYPE_OPERATOR_30 = 1030;
+    const int SERVICE_TYPE_OPERATOR_31 = 1031;
+    const int SERVICE_TYPE_OPERATOR_32 = 1032;
+    /**
+     * Combined list of barring services for UTRAN, EUTRAN, and NGRAN.
+     *
+     * Barring information is defined in:
+     * -UTRAN - 3gpp 25.331 Sec 10.2.48.8.6.
+     * -EUTRAN - 3gpp 36.331 Sec 6.3.1 SystemInformationBlockType2
+     * -NGRAN - 3gpp 38.331 Sec 6.3.2 UAC-BarringInfo and 22.261 Sec 6.22.2.[2-3]
+     * Values are SERVICE_TYPE_
+     */
+    int serviceType;
+    /**
+     * The type of barring applied to the service
+     * Values are BARRING_TYPE_
+     */
+    int barringType;
+    /**
+     * Type-specific barring info if applicable
+     */
+    @nullable BarringTypeSpecificInfo barringTypeSpecificInfo;
+}
diff --git a/radio/aidl/android/hardware/radio/network/BarringTypeSpecificInfo.aidl b/radio/aidl/android/hardware/radio/network/BarringTypeSpecificInfo.aidl
new file mode 100644
index 0000000..3db3bf3
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/BarringTypeSpecificInfo.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable BarringTypeSpecificInfo {
+    /**
+     * The barring factor as a percentage 0-100
+     */
+    int factor;
+    /**
+     * The number of seconds between re-evaluations of barring
+     */
+    int timeSeconds;
+    /**
+     * Indicates whether barring is currently being applied.
+     *
+     * <p>True if the UE applies barring to a conditionally barred service based on the conditional
+     * barring parameters.
+     *
+     * <p>False if the service is conditionally barred but barring is not currently applied, which
+     * could be due to either the barring criteria not having been evaluated (if the UE has not
+     * attempted to use the service) or due to the criteria being evaluated and the UE being
+     * permitted to use the service despite conditional barring.
+     */
+    boolean isBarred;
+}
diff --git a/radio/aidl/android/hardware/radio/network/Cdma2000RegistrationInfo.aidl b/radio/aidl/android/hardware/radio/network/Cdma2000RegistrationInfo.aidl
new file mode 100644
index 0000000..b06fabb
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/Cdma2000RegistrationInfo.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable Cdma2000RegistrationInfo {
+    const int PRL_INDICATOR_NOT_REGISTERED = -1;
+    const int PRL_INDICATOR_NOT_IN_PRL = 0;
+    const int PRL_INDICATOR_IN_PRL = 1;
+    /**
+     * Concurrent services support indicator. if registered on a CDMA system.
+     * false - Concurrent services not supported,
+     * true - Concurrent services supported
+     */
+    boolean cssSupported;
+    /**
+     * TSB-58 Roaming Indicator if registered on a CDMA or EVDO system or -1 if not.
+     * Valid values are 0-255.
+     */
+    int roamingIndicator;
+    /**
+     * Indicates whether the current system is in the PRL if registered on a CDMA or EVDO system
+     * or -1 if not. 0=not in the PRL, 1=in the PRL.
+     * Values are PRL_INDICATOR_
+     */
+    int systemIsInPrl;
+    /**
+     * Default Roaming Indicator from the PRL if registered on a CDMA or EVDO system or -1 if not.
+     * Valid values are 0-255.
+     */
+    int defaultRoamingIndicator;
+}
diff --git a/radio/aidl/android/hardware/radio/network/CdmaRoamingType.aidl b/radio/aidl/android/hardware/radio/network/CdmaRoamingType.aidl
new file mode 100644
index 0000000..2fea519
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/CdmaRoamingType.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum CdmaRoamingType {
+    HOME_NETWORK,
+    AFFILIATED_ROAM,
+    ANY_ROAM,
+}
diff --git a/radio/aidl/android/hardware/radio/network/CdmaSignalStrength.aidl b/radio/aidl/android/hardware/radio/network/CdmaSignalStrength.aidl
new file mode 100644
index 0000000..1286f67
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/CdmaSignalStrength.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable CdmaSignalStrength {
+    /**
+     * This value is the actual RSSI value multiplied by -1. Example: If the actual RSSI is -75,
+     * then this response value will be 75. INT_MAX means invalid/unreported.
+     */
+    int dbm;
+    /**
+     * This value is the actual Ec/Io multiplied by -10. Example: If the actual Ec/Io is -12.5 dB,
+     * then this response value will be 125. INT_MAX means invalid/unreported.
+     */
+    int ecio;
+}
diff --git a/radio/aidl/android/hardware/radio/network/CellConnectionStatus.aidl b/radio/aidl/android/hardware/radio/network/CellConnectionStatus.aidl
new file mode 100644
index 0000000..da36ff0
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/CellConnectionStatus.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum CellConnectionStatus {
+    /**
+     * Cell is not a serving cell.
+     */
+    NONE,
+    /**
+     * UE has connection to cell for signaling and possibly data (3GPP 36.331, 25.331).
+     */
+    PRIMARY_SERVING,
+    /**
+     * UE has connection to cell for data (3GPP 36.331, 25.331).
+     */
+    SECONDARY_SERVING,
+}
diff --git a/radio/aidl/android/hardware/radio/network/CellIdentity.aidl b/radio/aidl/android/hardware/radio/network/CellIdentity.aidl
new file mode 100644
index 0000000..e34866b
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/CellIdentity.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+import android.hardware.radio.network.CellIdentityCdma;
+import android.hardware.radio.network.CellIdentityGsm;
+import android.hardware.radio.network.CellIdentityLte;
+import android.hardware.radio.network.CellIdentityNr;
+import android.hardware.radio.network.CellIdentityTdscdma;
+import android.hardware.radio.network.CellIdentityWcdma;
+
+/**
+ * A union representing the CellIdentity of a single cell.
+ */
+@VintfStability
+@JavaDerive(toString=true)
+union CellIdentity {
+    boolean noinit;
+    CellIdentityGsm gsm;
+    CellIdentityWcdma wcdma;
+    CellIdentityTdscdma tdscdma;
+    CellIdentityCdma cdma;
+    CellIdentityLte lte;
+    CellIdentityNr nr;
+}
diff --git a/radio/aidl/android/hardware/radio/network/CellIdentityCdma.aidl b/radio/aidl/android/hardware/radio/network/CellIdentityCdma.aidl
new file mode 100644
index 0000000..5bb26c1
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/CellIdentityCdma.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+import android.hardware.radio.network.OperatorInfo;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable CellIdentityCdma {
+    /**
+     * Network Id 0..65535, INT_MAX if unknown
+     */
+    int networkId;
+    /**
+     * CDMA System Id 0..32767, INT_MAX if unknown
+     */
+    int systemId;
+    /**
+     * Base Station Id 0..65535, INT_MAX if unknown
+     */
+    int baseStationId;
+    /**
+     * Longitude is a decimal number as specified in 3GPP2 C.S0005-A v6.0. It is represented in
+     * units of 0.25 seconds and ranges from -2592000 to 2592000, both values inclusive
+     * (corresponding to a range of -180 to +180 degrees). INT_MAX if unknown
+     */
+    int longitude;
+    /**
+     * Latitude is a decimal number as specified in 3GPP2 C.S0005-A v6.0. It is represented in
+     * units of 0.25 seconds and ranges from -1296000 to 1296000, both values inclusive
+     * (corresponding to a range of -90 to +90 degrees). INT_MAX if unknown
+     */
+    int latitude;
+    /**
+     * OperatorInfo containing alphaLong and alphaShort
+     */
+    OperatorInfo operatorNames;
+}
diff --git a/radio/aidl/android/hardware/radio/network/CellIdentityGsm.aidl b/radio/aidl/android/hardware/radio/network/CellIdentityGsm.aidl
new file mode 100644
index 0000000..60f42b6
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/CellIdentityGsm.aidl
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+import android.hardware.radio.network.OperatorInfo;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable CellIdentityGsm {
+    /**
+     * 3-digit Mobile Country Code, 0..999, empty string if unknown
+     */
+    String mcc;
+    /**
+     * 2 or 3-digit Mobile Network Code, 0..999, empty string if unknown
+     */
+    String mnc;
+    /**
+     * 16-bit Location Area Code, 0..65535, INT_MAX if unknown
+     */
+    int lac;
+    /**
+     * 16-bit GSM Cell Identity described in TS 27.007, 0..65535, INT_MAX if unknown
+     */
+    int cid;
+    /**
+     * 16-bit GSM Absolute RF channel number; this value must be valid
+     */
+    int arfcn;
+    /**
+     * 6-bit Base Station Identity Code, 0xFF if unknown
+     */
+    byte bsic;
+    /**
+     * OperatorInfo containing alphaLong and alphaShort
+     */
+    OperatorInfo operatorNames;
+    /**
+     * Additional PLMN-IDs beyond the primary PLMN broadcast for this cell
+     */
+    String[] additionalPlmns;
+}
diff --git a/radio/aidl/android/hardware/radio/network/CellIdentityLte.aidl b/radio/aidl/android/hardware/radio/network/CellIdentityLte.aidl
new file mode 100644
index 0000000..bfa58ac
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/CellIdentityLte.aidl
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+import android.hardware.radio.network.ClosedSubscriberGroupInfo;
+import android.hardware.radio.network.EutranBands;
+import android.hardware.radio.network.OperatorInfo;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable CellIdentityLte {
+    /**
+     * 3-digit Mobile Country Code, 0..999, empty string if unknown
+     */
+    String mcc;
+    /**
+     * 2 or 3-digit Mobile Network Code, 0..999, empty string if unknown
+     */
+    String mnc;
+    /**
+     * 28-bit Cell Identity described in TS TS 27.007, INT_MAX if unknown
+     */
+    int ci;
+    /**
+     * Physical cell id 0..503; this value must be valid
+     */
+    int pci;
+    /**
+     * 16-bit tracking area code, INT_MAX if unknown
+     */
+    int tac;
+    /**
+     * 18-bit LTE Absolute RF Channel Number; this value must be valid
+     */
+    int earfcn;
+    /**
+     * OperatorInfo containing alphaLong and alphaShort
+     */
+    OperatorInfo operatorNames;
+    /**
+     * Cell bandwidth, in kHz.
+     */
+    int bandwidth;
+    /**
+     * Additional PLMN-IDs beyond the primary PLMN broadcast for this cell
+     */
+    String[] additionalPlmns;
+    /**
+     * Information about any closed subscriber group ID for this cell
+     */
+    @nullable ClosedSubscriberGroupInfo csgInfo;
+    /**
+     * Bands used by the cell.
+     */
+    EutranBands[] bands;
+}
diff --git a/radio/aidl/android/hardware/radio/network/CellIdentityNr.aidl b/radio/aidl/android/hardware/radio/network/CellIdentityNr.aidl
new file mode 100644
index 0000000..d51a18e
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/CellIdentityNr.aidl
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+import android.hardware.radio.network.NgranBands;
+import android.hardware.radio.network.OperatorInfo;
+
+/**
+ * The CellIdentity structure should be reported once for each element of the PLMN-IdentityInfoList
+ * broadcast in SIB1 CellAccessRelatedInfo as per 3GPP TS 38.331 Section 6.3.2.
+ */
+@VintfStability
+@JavaDerive(toString=true)
+parcelable CellIdentityNr {
+    /**
+     * 3-digit Mobile Country Code, in range[0, 999]; This value must be valid for registered or
+     *  camped cells; INT_MAX means invalid/unreported.
+     */
+    String mcc;
+    /**
+     * 2 or 3-digit Mobile Network Code, in range [0, 999], This value must be valid for
+     * registered or camped cells; INT_MAX means invalid/unreported.
+     */
+    String mnc;
+    /**
+     * NR Cell Identity in range [0, 68719476735] (36 bits) described in 3GPP TS 38.331, which
+     * unambiguously identifies a cell within a PLMN. This value must be valid for registered or
+     * camped cells; LONG_MAX (2^63-1) means invalid/unreported.
+     */
+    long nci;
+    /**
+     * Physical cell id in range [0, 1007] described in 3GPP TS 38.331. This value must be valid.
+     */
+    int pci;
+    /**
+     * 16-bit tracking area code, INT_MAX means invalid/unreported.
+     */
+    int tac;
+    /**
+     * NR Absolute Radio Frequency Channel Number, in range [0, 3279165].
+     * Reference: 3GPP TS 38.101-1 and 3GPP TS 38.101-2 section 5.4.2.1.
+     * This value must be valid.
+     */
+    int nrarfcn;
+    /**
+     * OperatorInfo containing alphaLong and alphaShort
+     */
+    OperatorInfo operatorNames;
+    /**
+     * Additional PLMN-IDs beyond the primary PLMN broadcast for this cell
+     */
+    String[] additionalPlmns;
+    /**
+     * Bands used by the cell.
+     */
+    NgranBands[] bands;
+}
diff --git a/radio/aidl/android/hardware/radio/network/CellIdentityTdscdma.aidl b/radio/aidl/android/hardware/radio/network/CellIdentityTdscdma.aidl
new file mode 100644
index 0000000..f6e790f
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/CellIdentityTdscdma.aidl
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+import android.hardware.radio.network.ClosedSubscriberGroupInfo;
+import android.hardware.radio.network.OperatorInfo;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable CellIdentityTdscdma {
+    /**
+     * 3-digit Mobile Country Code, 0..999, empty string if unknown.
+     */
+    String mcc;
+    /**
+     * 2 or 3-digit Mobile Network Code, 0..999, empty string if unknown.
+     */
+    String mnc;
+    /**
+     * 16-bit Location Area Code, 0..65535, INT_MAX if unknown.
+     */
+    int lac;
+    /**
+     * 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, INT_MAX if unknown.
+     */
+    int cid;
+    /**
+     * 8-bit Cell Parameters ID described in TS 25.331, 0..127, INT_MAX if unknown.
+     */
+    int cpid;
+    /**
+     * 16-bit UMTS Absolute RF Channel Number defined in TS 25.102 5.4.4; this value must be valid.
+     */
+    int uarfcn;
+    /**
+     * OperatorInfo containing alphaLong and alphaShort
+     */
+    OperatorInfo operatorNames;
+    /**
+     * Additional PLMN-IDs beyond the primary PLMN broadcast for this cell.
+     */
+    String[] additionalPlmns;
+    /**
+     * Information about any closed subscriber group ID for this cell.
+     */
+    @nullable ClosedSubscriberGroupInfo csgInfo;
+}
diff --git a/radio/aidl/android/hardware/radio/network/CellIdentityWcdma.aidl b/radio/aidl/android/hardware/radio/network/CellIdentityWcdma.aidl
new file mode 100644
index 0000000..a76509b
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/CellIdentityWcdma.aidl
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+import android.hardware.radio.network.ClosedSubscriberGroupInfo;
+import android.hardware.radio.network.OperatorInfo;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable CellIdentityWcdma {
+    /**
+     * 3-digit Mobile Country Code, 0..999, empty string if unknown.
+     */
+    String mcc;
+    /**
+     * 2 or 3-digit Mobile Network Code, 0..999, empty string if unknown.
+     */
+    String mnc;
+    /**
+     * 16-bit Location Area Code, 0..65535, INT_MAX if unknown.
+     */
+    int lac;
+    /**
+     * 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, INT_MAX if unknown.
+     */
+    int cid;
+    /**
+     * 9-bit UMTS Primary Scrambling Code described in TS 25.331, 0..511; this value must be valid.
+     */
+    int psc;
+    /**
+     * 16-bit UMTS Absolute RF Channel Number; this value must be valid.
+     */
+    int uarfcn;
+    /**
+     * OperatorInfo containing alphaLong and alphaShort
+     */
+    OperatorInfo operatorNames;
+    /**
+     * Additional PLMN-IDs beyond the primary PLMN broadcast for this cell.
+     */
+    String[] additionalPlmns;
+    /**
+     * Information about any closed subscriber group ID for this cell.
+     */
+    @nullable ClosedSubscriberGroupInfo csgInfo;
+}
diff --git a/radio/aidl/android/hardware/radio/network/CellInfo.aidl b/radio/aidl/android/hardware/radio/network/CellInfo.aidl
new file mode 100644
index 0000000..161ac71
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/CellInfo.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+import android.hardware.radio.network.CellConnectionStatus;
+import android.hardware.radio.network.CellInfoRatSpecificInfo;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable CellInfo {
+    /**
+     * True if this cell is registered false if not registered.
+     */
+    boolean registered;
+    /**
+     * Connection status for the cell.
+     */
+    CellConnectionStatus connectionStatus;
+    CellInfoRatSpecificInfo ratSpecificInfo;
+}
diff --git a/radio/aidl/android/hardware/radio/network/CellInfoCdma.aidl b/radio/aidl/android/hardware/radio/network/CellInfoCdma.aidl
new file mode 100644
index 0000000..5408104
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/CellInfoCdma.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+import android.hardware.radio.network.CdmaSignalStrength;
+import android.hardware.radio.network.CellIdentityCdma;
+import android.hardware.radio.network.EvdoSignalStrength;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable CellInfoCdma {
+    CellIdentityCdma cellIdentityCdma;
+    CdmaSignalStrength signalStrengthCdma;
+    EvdoSignalStrength signalStrengthEvdo;
+}
diff --git a/radio/aidl/android/hardware/radio/network/CellInfoGsm.aidl b/radio/aidl/android/hardware/radio/network/CellInfoGsm.aidl
new file mode 100644
index 0000000..cadcd91
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/CellInfoGsm.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+import android.hardware.radio.network.CellIdentityGsm;
+import android.hardware.radio.network.GsmSignalStrength;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable CellInfoGsm {
+    CellIdentityGsm cellIdentityGsm;
+    GsmSignalStrength signalStrengthGsm;
+}
diff --git a/radio/aidl/android/hardware/radio/network/CellInfoLte.aidl b/radio/aidl/android/hardware/radio/network/CellInfoLte.aidl
new file mode 100644
index 0000000..443a668
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/CellInfoLte.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+import android.hardware.radio.network.CellIdentityLte;
+import android.hardware.radio.network.LteSignalStrength;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable CellInfoLte {
+    CellIdentityLte cellIdentityLte;
+    LteSignalStrength signalStrengthLte;
+}
diff --git a/radio/aidl/android/hardware/radio/network/CellInfoNr.aidl b/radio/aidl/android/hardware/radio/network/CellInfoNr.aidl
new file mode 100644
index 0000000..6b3d4f4
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/CellInfoNr.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+import android.hardware.radio.network.CellIdentityNr;
+import android.hardware.radio.network.NrSignalStrength;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable CellInfoNr {
+    CellIdentityNr cellIdentityNr;
+    NrSignalStrength signalStrengthNr;
+}
diff --git a/radio/aidl/android/hardware/radio/network/CellInfoRatSpecificInfo.aidl b/radio/aidl/android/hardware/radio/network/CellInfoRatSpecificInfo.aidl
new file mode 100644
index 0000000..76e92a4
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/CellInfoRatSpecificInfo.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+import android.hardware.radio.network.CellInfoCdma;
+import android.hardware.radio.network.CellInfoGsm;
+import android.hardware.radio.network.CellInfoLte;
+import android.hardware.radio.network.CellInfoNr;
+import android.hardware.radio.network.CellInfoTdscdma;
+import android.hardware.radio.network.CellInfoWcdma;
+
+@VintfStability
+@JavaDerive(toString=true)
+union CellInfoRatSpecificInfo {
+    /**
+     * 3gpp CellInfo types.
+     */
+    CellInfoGsm gsm;
+    CellInfoWcdma wcdma;
+    CellInfoTdscdma tdscdma;
+    CellInfoLte lte;
+    CellInfoNr nr;
+    /**
+     * 3gpp2 CellInfo types;
+     */
+    CellInfoCdma cdma;
+}
diff --git a/radio/aidl/android/hardware/radio/network/CellInfoTdscdma.aidl b/radio/aidl/android/hardware/radio/network/CellInfoTdscdma.aidl
new file mode 100644
index 0000000..fb9c984
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/CellInfoTdscdma.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+import android.hardware.radio.network.CellIdentityTdscdma;
+import android.hardware.radio.network.TdscdmaSignalStrength;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable CellInfoTdscdma {
+    CellIdentityTdscdma cellIdentityTdscdma;
+    TdscdmaSignalStrength signalStrengthTdscdma;
+}
diff --git a/radio/aidl/android/hardware/radio/network/CellInfoWcdma.aidl b/radio/aidl/android/hardware/radio/network/CellInfoWcdma.aidl
new file mode 100644
index 0000000..2d6a2e5
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/CellInfoWcdma.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+import android.hardware.radio.network.CellIdentityWcdma;
+import android.hardware.radio.network.WcdmaSignalStrength;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable CellInfoWcdma {
+    CellIdentityWcdma cellIdentityWcdma;
+    WcdmaSignalStrength signalStrengthWcdma;
+}
diff --git a/radio/aidl/android/hardware/radio/network/ClosedSubscriberGroupInfo.aidl b/radio/aidl/android/hardware/radio/network/ClosedSubscriberGroupInfo.aidl
new file mode 100644
index 0000000..a2d82d7
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/ClosedSubscriberGroupInfo.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable ClosedSubscriberGroupInfo {
+    /**
+     * Indicates whether the cell is restricted to only CSG members. A cell not broadcasting the
+     * CSG Indication but reporting CSG information is considered a Hybrid Cell.
+     * Refer to the "csg-Indication" field in 3GPP TS 36.331 section 6.2.2
+     * SystemInformationBlockType1.
+     * Also refer to "CSG Indicator" in 3GPP TS 25.331 section 10.2.48.8.1 and TS 25.304.
+     */
+    boolean csgIndication;
+    /**
+     * The human-readable name of the closed subscriber group operating this cell.
+     * Refer to "hnb-Name" in TS 36.331 section 6.2.2 SystemInformationBlockType9.
+     * Also refer to "HNB Name" in 3GPP TS25.331 section 10.2.48.8.23 and TS 23.003 section 4.8.
+     */
+    String homeNodebName;
+    /**
+     * The identity of the closed subscriber group that the cell belongs to.
+     * Refer to "CSG-Identity" in TS 36.336 section 6.3.4.
+     * Also refer to "CSG Identity" in 3GPP TS 25.331 section 10.3.2.8 and TS 23.003 section 4.7.
+     */
+    int csgIdentity;
+}
diff --git a/radio/aidl/android/hardware/radio/network/Domain.aidl b/radio/aidl/android/hardware/radio/network/Domain.aidl
new file mode 100644
index 0000000..be5f320
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/Domain.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum Domain {
+    /**
+     * Circuit-switched
+     */
+    CS = 1 << 0,
+    /**
+     * Packet-switched
+     */
+    PS = 1 << 1,
+}
diff --git a/radio/aidl/android/hardware/radio/network/EutranBands.aidl b/radio/aidl/android/hardware/radio/network/EutranBands.aidl
new file mode 100644
index 0000000..72e76e3
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/EutranBands.aidl
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+/**
+ * EUTRAN bands up to V16.4.0
+ */
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum EutranBands {
+    BAND_1 = 1,
+    BAND_2 = 2,
+    BAND_3 = 3,
+    BAND_4 = 4,
+    BAND_5 = 5,
+    BAND_6 = 6,
+    BAND_7 = 7,
+    BAND_8 = 8,
+    BAND_9 = 9,
+    BAND_10 = 10,
+    BAND_11 = 11,
+    BAND_12 = 12,
+    BAND_13 = 13,
+    BAND_14 = 14,
+    BAND_17 = 17,
+    BAND_18 = 18,
+    BAND_19 = 19,
+    BAND_20 = 20,
+    BAND_21 = 21,
+    BAND_22 = 22,
+    BAND_23 = 23,
+    BAND_24 = 24,
+    BAND_25 = 25,
+    BAND_26 = 26,
+    BAND_27 = 27,
+    BAND_28 = 28,
+    BAND_30 = 30,
+    BAND_31 = 31,
+    BAND_33 = 33,
+    BAND_34 = 34,
+    BAND_35 = 35,
+    BAND_36 = 36,
+    BAND_37 = 37,
+    BAND_38 = 38,
+    BAND_39 = 39,
+    BAND_40 = 40,
+    BAND_41 = 41,
+    BAND_42 = 42,
+    BAND_43 = 43,
+    BAND_44 = 44,
+    BAND_45 = 45,
+    BAND_46 = 46,
+    BAND_47 = 47,
+    BAND_48 = 48,
+    BAND_65 = 65,
+    BAND_66 = 66,
+    BAND_68 = 68,
+    BAND_70 = 70,
+    BAND_49 = 49,
+    BAND_50 = 50,
+    BAND_51 = 51,
+    BAND_52 = 52,
+    BAND_53 = 53,
+    BAND_71 = 71,
+    BAND_72 = 72,
+    BAND_73 = 73,
+    BAND_74 = 74,
+    BAND_85 = 85,
+    BAND_87 = 87,
+    BAND_88 = 88,
+}
diff --git a/radio/aidl/android/hardware/radio/network/EutranRegistrationInfo.aidl b/radio/aidl/android/hardware/radio/network/EutranRegistrationInfo.aidl
new file mode 100644
index 0000000..c9563ac
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/EutranRegistrationInfo.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+import android.hardware.radio.network.LteVopsInfo;
+import android.hardware.radio.network.NrIndicators;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable EutranRegistrationInfo {
+    /**
+     * Network capabilities for voice over PS services. This info is valid only on LTE network and
+     * must be present when device is camped on LTE. VopsInfo must be empty when device is camped
+     * only on 2G/3G.
+     */
+    LteVopsInfo lteVopsInfo;
+    /**
+     * The parameters of NR 5G Non-Standalone. This value is only valid on E-UTRAN, otherwise must
+     * be empty.
+     */
+    NrIndicators nrIndicators;
+}
diff --git a/radio/aidl/android/hardware/radio/network/EvdoSignalStrength.aidl b/radio/aidl/android/hardware/radio/network/EvdoSignalStrength.aidl
new file mode 100644
index 0000000..c3b3898
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/EvdoSignalStrength.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable EvdoSignalStrength {
+    /**
+     * This value is the actual RSSI value multiplied by -1. Example: If the actual RSSI is -75,
+     * then this response value will be 75; INT_MAX means invalid/unreported.
+     */
+    int dbm;
+    /**
+     * This value is the actual Ec/Io multiplied by -10. Example: If the actual Ec/Io is -12.5 dB,
+     * then this response value will be 125; INT_MAX means invalid/unreported.
+     */
+    int ecio;
+    /**
+     * Valid values are 0-8. 8 is the highest signal to noise ratio; INT_MAX means
+     * invalid/unreported.
+     */
+    int signalNoiseRatio;
+}
diff --git a/radio/aidl/android/hardware/radio/network/GeranBands.aidl b/radio/aidl/android/hardware/radio/network/GeranBands.aidl
new file mode 100644
index 0000000..0e5b7b2
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/GeranBands.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum GeranBands {
+    BAND_T380 = 1,
+    BAND_T410 = 2,
+    BAND_450 = 3,
+    BAND_480 = 4,
+    BAND_710 = 5,
+    BAND_750 = 6,
+    BAND_T810 = 7,
+    BAND_850 = 8,
+    BAND_P900 = 9,
+    BAND_E900 = 10,
+    BAND_R900 = 11,
+    BAND_DCS1800 = 12,
+    BAND_PCS1900 = 13,
+    BAND_ER900 = 14,
+}
diff --git a/radio/aidl/android/hardware/radio/network/GsmSignalStrength.aidl b/radio/aidl/android/hardware/radio/network/GsmSignalStrength.aidl
new file mode 100644
index 0000000..796f80f
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/GsmSignalStrength.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable GsmSignalStrength {
+    /**
+     * Valid values are (0-61, 99) as defined in TS 27.007 8.69; INT_MAX means invalid/unreported.
+     */
+    int signalStrength;
+    /**
+     * Bit error rate (0-7, 99) as defined in TS 27.007 8.5; INT_MAX means invalid/unreported.
+     */
+    int bitErrorRate;
+    /**
+     * Timing advance in bit periods. 1 bit period = 48/13 us. INT_MAX means invalid/unreported.
+     */
+    int timingAdvance;
+}
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
new file mode 100644
index 0000000..cce52ff
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
@@ -0,0 +1,440 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+import android.hardware.radio.AccessNetwork;
+import android.hardware.radio.network.CdmaRoamingType;
+import android.hardware.radio.network.IRadioNetworkIndication;
+import android.hardware.radio.network.IRadioNetworkResponse;
+import android.hardware.radio.network.IndicationFilter;
+import android.hardware.radio.network.NetworkScanRequest;
+import android.hardware.radio.network.NrDualConnectivityState;
+import android.hardware.radio.network.RadioAccessSpecifier;
+import android.hardware.radio.network.RadioBandMode;
+import android.hardware.radio.network.SignalThresholdInfo;
+import android.hardware.radio.network.UsageSetting;
+
+/**
+ * This interface is used by telephony and telecom to talk to cellular radio for network APIs.
+ * All the functions have minimum one parameter:
+ * serial: which corresponds to serial no. of request. Serial numbers must only be memorized for the
+ * duration of a method call. If clients provide colliding serials (including passing the same
+ * serial to different methods), multiple responses (one for each method call) must still be served.
+ * setResponseFunctions must work with IRadioNetworkResponse and IRadioNetworkIndication.
+ */
+@VintfStability
+oneway interface IRadioNetwork {
+    /**
+     * Requests bitmap representing the currently allowed network types.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioNetworkResponse.getAllowedNetworkTypesBitmapResponse()
+     */
+    void getAllowedNetworkTypesBitmap(in int serial);
+
+    /**
+     * Get the list of band modes supported by RF.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioNetworkResponse.getAvailableBandModesResponse()
+     */
+    void getAvailableBandModes(in int serial);
+
+    /**
+     * Scans for available networks
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioNetworkResponse.getAvailableNetworksResponse()
+     */
+    void getAvailableNetworks(in int serial);
+
+    /**
+     * Get all the barring info for the current camped cell applicable to the current user.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioNetworkResponse.getBarringInfoResponse()
+     */
+    void getBarringInfo(in int serial);
+
+    /**
+     * Request the actual setting of the roaming preferences in CDMA in the modem
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioNetworkResponse.getCdmaRoamingPreferenceResponse()
+     */
+    void getCdmaRoamingPreference(in int serial);
+
+    /**
+     * Request all of the current cell information known to the radio. The radio must return a list
+     * of all current cells, including the neighboring cells. If for a particular cell information
+     * isn't known then the appropriate unknown value will be returned.
+     * This does not cause or change the rate of unsolicited cellInfoList().
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioNetworkResponse.getCellInfoListResponse()
+     */
+    void getCellInfoList(in int serial);
+
+    /**
+     * Request current data registration state.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioNetworkResponse.getDataRegistrationStateResponse()
+     */
+    void getDataRegistrationState(in int serial);
+
+    /**
+     * Request current IMS registration state
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioNetworkResponse.getImsRegistrationStateResponse()
+     */
+    void getImsRegistrationState(in int serial);
+
+    /**
+     * Query current network selection mode
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioNetworkResponse.getNetworkSelectionModeResponse()
+     */
+    void getNetworkSelectionMode(in int serial);
+
+    /**
+     * Request current operator ONS or EONS
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioNetworkResponse.getOperatorResponse()
+     */
+    void getOperator(in int serial);
+
+    /**
+     * Requests current signal strength and associated information. Must succeed if radio is on.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioNetworkResponse.getSignalStrengthResponse()
+     */
+    void getSignalStrength(in int serial);
+
+    /**
+     * Get which bands the modem's background scan is acting on.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioNetworkResponse.getSystemSelectionChannelsResponse()
+     */
+    void getSystemSelectionChannels(in int serial);
+
+    /**
+     * Query the radio technology type (3GPP/3GPP2) used for voice. Query is valid only
+     * when radio state is not RADIO_STATE_UNAVAILABLE
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioNetworkResponse.getVoiceRadioTechnologyResponse()
+     */
+    void getVoiceRadioTechnology(in int serial);
+
+    /**
+     * Request current voice registration state.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioNetworkResponse.getVoiceRegistrationStateResponse()
+     */
+    void getVoiceRegistrationState(in int serial);
+
+    /**
+     * Is E-UTRA-NR Dual Connectivity enabled
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioNetworkResponse.isNrDualConnectivityEnabledResponse()
+     */
+    void isNrDualConnectivityEnabled(in int serial);
+
+    /**
+     * When response type received from a radio indication or radio response is
+     * RadioIndicationType:UNSOLICITED_ACK_EXP or RadioResponseType:SOLICITED_ACK_EXP respectively,
+     * acknowledge the receipt of those messages by sending responseAcknowledgement().
+     */
+    void responseAcknowledgement();
+
+    /**
+     * Requests to set the network type for searching and registering. Instruct the radio to
+     * *only* accept the types of network provided. In case of an emergency call, the modem is
+     * authorized to bypass this restriction.
+     *
+     * @param serial Serial number of request.
+     * @param networkTypeBitmap a 32-bit bearer bitmap of RadioAccessFamily
+     *
+     * Response function is IRadioNetworkResponse.setAllowedNetworkTypesBitmapResponse()
+     */
+    void setAllowedNetworkTypesBitmap(in int serial, in int networkTypeBitmap);
+
+    /**
+     * Assign a specified band for RF configuration.
+     *
+     * @param serial Serial number of request.
+     * @param mode RadioBandMode
+     *
+     * Response function is IRadioNetworkResponse.setBandModeResponse()
+     */
+    void setBandMode(in int serial, in RadioBandMode mode);
+
+    /**
+     * Change call barring facility password
+     *
+     * @param serial Serial number of request.
+     * @param facility facility string code from TS 27.007 7.4 (eg "AO" for BAOC)
+     * @param oldPassword old password
+     * @param newPassword new password
+     *
+     * Response function is IRadioNetworkResponse.setBarringPasswordResponse()
+     */
+    void setBarringPassword(
+            in int serial, in String facility, in String oldPassword, in String newPassword);
+
+    /**
+     * Request to set the roaming preferences in CDMA
+     *
+     * @param serial Serial number of request.
+     * @param type CdmaRoamingType defined in types.hal
+     *
+     * Response function is IRadioNetworkResponse.setCdmaRoamingPreferenceResponse()
+     */
+    void setCdmaRoamingPreference(in int serial, in CdmaRoamingType type);
+
+    /**
+     * Sets the minimum time between when unsolicited cellInfoList() must be invoked.
+     * A value of 0, means invoke cellInfoList() when any of the reported information changes.
+     * Setting the value to INT_MAX(0x7fffffff) means never issue a unsolicited cellInfoList().
+     *
+     * @param serial Serial number of request.
+     * @param rate minimum time in milliseconds to indicate time between unsolicited cellInfoList()
+     *
+     * Response function is IRadioNetworkResponse.setCellInfoListRateResponse()
+     */
+    void setCellInfoListRate(in int serial, in int rate);
+
+    /**
+     * Sets the indication filter. Prevents the reporting of specified unsolicited indications from
+     * the radio. This is used for power saving in instances when those indications are not needed.
+     * If unset, defaults to IndicationFilter:ALL.
+     *
+     * @param serial Serial number of request.
+     * @param indicationFilter 32-bit bitmap of IndicationFilter. Bits set to 1 indicate the
+     *        indications are enabled. See IndicationFilter for the definition of each bit.
+     *
+     * Response function is IRadioNetworkResponse.setIndicationFilterResponse()
+     */
+    void setIndicationFilter(in int serial, in int indicationFilter);
+
+    /**
+     * Sets the link capacity reporting criteria. The resulting reporting criteria are the AND of
+     * all the supplied criteria. Note that reporting criteria must be individually set for each
+     * RAN. If unset, reporting criteria for that RAN are implementation-defined.
+     *
+     * @param serial Serial number of request.
+     * @param hysteresisMs A hysteresis time in milliseconds to prevent flapping. A value of 0
+     *        disables hysteresis.
+     * @param hysteresisDlKbps An interval in kbps defining the required magnitude change between DL
+     *        reports. hysteresisDlKbps must be smaller than the smallest threshold delta. A value
+     *        of 0 disables hysteresis.
+     * @param hysteresisUlKbps An interval in kbps defining the required magnitude change between UL
+     *        reports. hysteresisUlKbps must be smaller than the smallest threshold delta. A value
+     *        of 0 disables hysteresis.
+     * @param thresholdsDownlinkKbps A vector of trigger thresholds in kbps for downlink reports. A
+     *        vector size of 0 disables the use of DL thresholds for reporting.
+     * @param thresholdsUplinkKbps A vector of trigger thresholds in kbps for uplink reports. A
+     *        vector size of 0 disables the use of UL thresholds for reporting.
+     * @param accessNetwork The type of network for which to apply these thresholds.
+     *
+     * Response function is IRadioNetworkResponse.setLinkCapacityReportingCriteriaResponse().
+     */
+    void setLinkCapacityReportingCriteria(in int serial, in int hysteresisMs,
+            in int hysteresisDlKbps, in int hysteresisUlKbps, in int[] thresholdsDownlinkKbps,
+            in int[] thresholdsUplinkKbps, in AccessNetwork accessNetwork);
+
+    /**
+     * Enables/disables network state change notifications due to changes in LAC and/or CID (for
+     * GSM) or BID/SID/NID/latitude/longitude (for CDMA). Basically +CREG=2 vs. +CREG=1 (TS 27.007).
+     * The Radio implementation must default to "updates enabled" when the screen is on and
+     * "updates disabled" when the screen is off.
+     *
+     * @param serial Serial number of request.
+     * @param enable true=updates enabled (+CREG=2), false=updates disabled (+CREG=1)
+     *
+     * Response function is IRadioNetworkResponse.setLocationUpdatesResponse()
+     */
+    void setLocationUpdates(in int serial, in boolean enable);
+
+    /**
+     * Specify that the network must be selected automatically.
+     * This request must not respond until the new operator is selected and registered.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioNetworkResponse.setNetworkSelectionModeAutomaticResponse()
+     */
+    void setNetworkSelectionModeAutomatic(in int serial);
+
+    /**
+     * Manually select a specified network. This request must not respond until the new operator is
+     * selected and registered. Per TS 23.122, the RAN is just the initial suggested value.
+     * If registration fails, the RAN is not available afterwards, or the RAN is not within the
+     * network types specified by IRadioNetwork::setAllowedNetworkTypeBitmap, then the modem will
+     * need to select the next best RAN for network registration.
+     *
+     * @param serial Serial number of request.
+     * @param operatorNumeric String specifying MCCMNC of network to select (eg "310170").
+     * @param ran Initial suggested access network type. If value is UNKNOWN, the modem will select
+     *        the next best RAN for network registration.
+     *
+     * Response function is IRadioNetworkResponse.setNetworkSelectionModeManualResponse()
+     */
+    void setNetworkSelectionModeManual(
+            in int serial, in String operatorNumeric, in AccessNetwork ran);
+
+    /**
+     * Enable or disable E-UTRA-NR dual connectivity. If disabled then UE will not connect
+     * to secondary carrier.
+     *
+     * @param serial Serial number of request.
+     * @param nrDualConnectivityState expected NR dual connectivity state.
+     *        1: Enable NR dual connectivity {NrDualConnectivityState:ENABLE}
+     *        2: Disable NR dual connectivity {NrDualConnectivityState:DISABLE}
+     *        3: Disable NR dual connectivity and force secondary cell to be released
+     *           {NrDualConnectivityState:DISABLE_IMMEDIATE}
+     *
+     * Response function is IRadioNetworkResponse.setNrDualConnectivityStateResponse()
+     */
+    void setNrDualConnectivityState(
+            in int serial, in NrDualConnectivityState nrDualConnectivityState);
+
+    /**
+     * Set response functions for network radio requests and indications.
+     *
+     * @param radioNetworkResponse Object containing response functions
+     * @param radioNetworkIndication Object containing radio indications
+     */
+    void setResponseFunctions(in IRadioNetworkResponse radioNetworkResponse,
+            in IRadioNetworkIndication radioNetworkIndication);
+
+    /**
+     * Sets or clears the signal strength reporting criteria for multiple RANs in one request.
+     *
+     * The reporting criteria are set individually for each combination of RAN and measurement type.
+     * For each RAN type, if no reporting criteria are set, then the reporting of SignalStrength for
+     * that RAN is implementation-defined. If any criteria are supplied for a RAN type, then
+     * SignalStrength is only reported as specified by those criteria. For any RAN types not defined
+     * by this HAL, reporting is implementation-defined.
+     *
+     * @param serial Serial number of request.
+     * @param signalThresholdInfos Collection of SignalThresholdInfo specifying the reporting
+     *        criteria. See SignalThresholdInfo for details.
+     *
+     * Response function is IRadioNetworkResponse.setSignalStrengthReportingCriteriaResponse()
+     */
+    void setSignalStrengthReportingCriteria(
+            in int serial, in SignalThresholdInfo[] signalThresholdInfos);
+
+    /**
+     * Enables/disables supplementary service related notifications from the network.
+     * Notifications are reported via unsolSuppSvcNotification().
+     *
+     * @param serial Serial number of request.
+     * @param enable true = notifications enabled, false = notifications disabled.
+     *
+     * Response function is IRadioNetworkResponse.setSuppServiceNotificationsResponse()
+     */
+    void setSuppServiceNotifications(in int serial, in boolean enable);
+
+    /**
+     * Specify which bands modem's background scan must act on. If specifyChannels is true, it only
+     * scans bands specified in specifiers. If specifyChannels is false, it scans all bands. For
+     * example, CBRS is only on LTE band 48. By specifying this band, modem saves more power.
+     *
+     * @param serial Serial number of request.
+     * @param specifyChannels whether to scan bands defined in specifiers.
+     * @param specifiers which bands to scan. Only used if specifyChannels is true.
+     *
+     * Response function is IRadioNetworkResponse.setSystemSelectionChannelsResponse()
+     */
+    void setSystemSelectionChannels(
+            in int serial, in boolean specifyChannels, in RadioAccessSpecifier[] specifiers);
+
+    /**
+     * Starts a network scan.
+     *
+     * @param serial Serial number of request.
+     * @param request Defines the radio networks/bands/channels which need to be scanned.
+     *
+     * Response function is IRadioNetworkResponse.startNetworkScanResponse()
+     */
+    void startNetworkScan(in int serial, in NetworkScanRequest request);
+
+    /**
+     * Stops ongoing network scan
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioNetworkResponse.stopNetworkScanResponse()
+     */
+    void stopNetworkScan(in int serial);
+
+    /**
+     * Requests that network personalization be deactivated
+     *
+     * @param serial Serial number of request.
+     * @param netPin Network depersonlization code
+     *
+     * Response function is IRadioNetworkResponse.supplyNetworkDepersonalizationResponse()
+     */
+    void supplyNetworkDepersonalization(in int serial, in String netPin);
+
+    /**
+     * Set the UE usage setting for data/voice centric usage.
+     *
+     * <p>Sets the usage setting in accordance with 3gpp 24.301 sec 4.3 and 3gpp 24.501 sec 4.3.
+     * <p>This value must be independently preserved for each SIM; (setting the value is not a
+     * "global" override).
+     *
+     * @param serial Serial number of request.
+     * @param usageSetting the usage setting for the current SIM.
+     */
+    oneway void setUsageSetting(in int serial, in UsageSetting usageSetting);
+
+    /**
+     * Get the UE usage setting for data/voice centric usage.
+     *
+     * <p>Gets the usage setting in accordance with 3gpp 24.301 sec 4.3 and 3gpp 24.501 sec 4.3.
+     *
+     * @param serial Serial number of request.
+     */
+    oneway void getUsageSetting(in int serial);
+}
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetworkIndication.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetworkIndication.aidl
new file mode 100644
index 0000000..f471433
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetworkIndication.aidl
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+import android.hardware.radio.RadioIndicationType;
+import android.hardware.radio.RadioTechnology;
+import android.hardware.radio.network.BarringInfo;
+import android.hardware.radio.network.CellIdentity;
+import android.hardware.radio.network.CellInfo;
+import android.hardware.radio.network.LinkCapacityEstimate;
+import android.hardware.radio.network.NetworkScanResult;
+import android.hardware.radio.network.PhoneRestrictedState;
+import android.hardware.radio.network.PhysicalChannelConfig;
+import android.hardware.radio.network.SignalStrength;
+import android.hardware.radio.network.SuppSvcNotification;
+
+/**
+ * Interface declaring unsolicited radio indications for network APIs.
+ */
+@VintfStability
+oneway interface IRadioNetworkIndication {
+    /**
+     * Indicate barring information for the user’s access category / access class and PLMN.
+     *
+     * <p>Provide information about the barring status of the cell for the user. The information
+     * provided should describe all barring configurations that are applicable to the current user,
+     * even if the user is not currently barred (due to conditional barring). This informs Android
+     * of likely future (statistical) barring for specific services.
+     *
+     * <p>This indication should be sent whenever the cell’s barring config changes for the current
+     * user, or if the user’s conditional barring status changes due to re-evaluation of the
+     * barring conditions. Barring status will likely change when the device camps for service,
+     * when PLMN selection is completed, when the device attempts to access a conditionally barred
+     * service, and when the System Information including barring info for a camped cell is updated.
+     *
+     * @param type Type of radio indication
+     * @param cellIdentity cellIdentity for the barring infos
+     * @param barringInfos a vector of BarringInfos for all barring service types
+     */
+    void barringInfoChanged(in RadioIndicationType type, in CellIdentity cellIdentity,
+            in BarringInfo[] barringInfos);
+
+    /**
+     * Indicates when PRL (preferred roaming list) changes.
+     *
+     * @param type Type of radio indication
+     * @param version PRL version after PRL changes
+     */
+    void cdmaPrlChanged(in RadioIndicationType type, in int version);
+
+    /**
+     * Report all of the current cell information known to the radio.
+     *
+     * @param type Type of radio indication
+     * @param records Current cell information
+     */
+    void cellInfoList(in RadioIndicationType type, in CellInfo[] records);
+
+    /**
+     * Indicates current link capacity estimate. This indication is sent whenever the reporting
+     * criteria, as set by IRadioNetwork.setLinkCapacityReportingCriteria(), are met and the
+     * indication is not suppressed by IRadioNetwork.setIndicationFilter().
+     *
+     * @param type Type of radio indication
+     * @param lce LinkCapacityEstimate
+     */
+    void currentLinkCapacityEstimate(in RadioIndicationType type, in LinkCapacityEstimate lce);
+
+    /**
+     * Indicates physical channel configurations. An empty configs list shall be returned when the
+     * radio is in idle mode (i.e. RRC idle).
+     *
+     * @param type Type of radio indication
+     * @param configs Vector of PhysicalChannelConfigs
+     */
+    void currentPhysicalChannelConfigs(
+            in RadioIndicationType type, in PhysicalChannelConfig[] configs);
+
+    /**
+     * Indicates current signal strength of the radio.
+     *
+     * @param type Type of radio indication
+     * @param signalStrength SignalStrength information
+     */
+    void currentSignalStrength(in RadioIndicationType type, in SignalStrength signalStrength);
+
+    /**
+     * Indicates when IMS registration state has changed. To get IMS registration state and IMS SMS
+     * format, callee needs to invoke getImsRegistrationState().
+     *
+     * @param type Type of radio indication
+     */
+    void imsNetworkStateChanged(in RadioIndicationType type);
+
+    /**
+     * Incremental network scan results.
+     *
+     * @param type Type of radio indication
+     * @param result the result of the network scan
+     */
+    void networkScanResult(in RadioIndicationType type, in NetworkScanResult result);
+
+    /**
+     * Indicates when voice or data network state changed. Callee must invoke
+     * IRadioNetwork.getVoiceRegistrationState(), IRadioNetwork.getDataRegistrationState(), and
+     * IRadioNetwork.getOperator()
+     *
+     * @param type Type of radio indication
+     */
+    void networkStateChanged(in RadioIndicationType type);
+
+    /**
+     * Indicates when radio has received a NITZ time message.
+     *
+     * @param type Type of radio indication
+     * @param nitzTime NITZ time string in the form "yy/mm/dd,hh:mm:ss(+/-)tz,dt"
+     * @param receivedTimeMs time (in milliseconds since boot) at which RIL sent the NITZ time to
+     *        the framework
+     * @param ageMs time in milliseconds indicating how long NITZ was cached in RIL and modem.
+     *        This must track true age and therefore must be calculated using clocks that
+     *        include the time spend in sleep / low power states. If it can not be guaranteed,
+     *        there must not be any caching done at the modem and should fill in 0 for ageMs
+     */
+    void nitzTimeReceived(
+            in RadioIndicationType type, in String nitzTime, in long receivedTimeMs, in long ageMs);
+
+    /**
+     * Report that Registration or a Location/Routing/Tracking Area update has failed.
+     *
+     * <p>Indicate whenever a registration procedure, including a location, routing, or tracking
+     * area update fails. This includes procedures that do not necessarily result in a change of
+     * the modem's registration status. If the modem's registration status changes, that is
+     * reflected in the onNetworkStateChanged() and subsequent get{Voice/Data}RegistrationState().
+     *
+     * @param cellIdentity the CellIdentity, which must include the globally unique identifier for
+     *        the cell (for example, all components of the CGI or ECGI).
+     * @param chosenPlmn a 5 or 6 digit alphanumeric PLMN (MCC|MNC) among those broadcast by the
+     *        cell that was chosen for the failed registration attempt.
+     * @param domain Domain::CS, Domain::PS, or both in case of a combined procedure.
+     * @param causeCode the primary failure cause code of the procedure.
+     *        For GSM/UMTS (MM), values are in TS 24.008 Sec 10.5.95
+     *        For GSM/UMTS (GMM), values are in TS 24.008 Sec 10.5.147
+     *        For LTE (EMM), cause codes are TS 24.301 Sec 9.9.3.9
+     *        For NR (5GMM), cause codes are TS 24.501 Sec 9.11.3.2
+     *        MAX_INT if this value is unused.
+     * @param additionalCauseCode the cause code of any secondary/combined procedure if appropriate.
+     *        For UMTS, if a combined attach succeeds for PS only, then the GMM cause code shall be
+     *        included as an additionalCauseCode.
+     *        For LTE (ESM), cause codes are in TS 24.301 9.9.4.4
+     *        MAX_INT if this value is unused.
+     */
+    void registrationFailed(in RadioIndicationType type, in CellIdentity cellIdentity,
+            in String chosenPlmn, in int domain, in int causeCode, in int additionalCauseCode);
+
+    /**
+     * Indicates a restricted state change (eg, for Domain Specific Access Control).
+     * Radio must send this msg after radio off/on cycle no matter it is changed or not.
+     *
+     * @param type Type of radio indication
+     * @param state Bitmask of restricted state as defined by PhoneRestrictedState
+     */
+    void restrictedStateChanged(in RadioIndicationType type, in PhoneRestrictedState state);
+
+    /**
+     * Reports supplementary service related notification from the network.
+     *
+     * @param type Type of radio indication
+     * @param suppSvc SuppSvcNotification
+     */
+    void suppSvcNotify(in RadioIndicationType type, in SuppSvcNotification suppSvc);
+
+    /**
+     * Indicates that voice technology has changed. Responds with new rat.
+     *
+     * @param type Type of radio indication
+     * @param rat Current new voice rat
+     */
+    void voiceRadioTechChanged(in RadioIndicationType type, in RadioTechnology rat);
+}
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
new file mode 100644
index 0000000..dcf0004
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
@@ -0,0 +1,575 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+import android.hardware.radio.RadioResponseInfo;
+import android.hardware.radio.RadioTechnology;
+import android.hardware.radio.RadioTechnologyFamily;
+import android.hardware.radio.network.BarringInfo;
+import android.hardware.radio.network.CdmaRoamingType;
+import android.hardware.radio.network.CellIdentity;
+import android.hardware.radio.network.CellInfo;
+import android.hardware.radio.network.OperatorInfo;
+import android.hardware.radio.network.RadioAccessSpecifier;
+import android.hardware.radio.network.RadioBandMode;
+import android.hardware.radio.network.RegStateResult;
+import android.hardware.radio.network.SignalStrength;
+import android.hardware.radio.network.UsageSetting;
+
+/**
+ * Interface declaring response functions to solicited radio requests for network APIs.
+ */
+@VintfStability
+oneway interface IRadioNetworkResponse {
+    /**
+     * Acknowledge the receipt of radio request sent to the vendor. This must be sent only for
+     * radio request which take long time to respond. For more details, refer
+     * https://source.android.com/devices/tech/connect/ril.html
+     *
+     * @param serial Serial no. of the request whose acknowledgement is sent.
+     */
+    void acknowledgeRequest(in int serial);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param networkTypeBitmap a 32-bit bitmap of RadioAccessFamily.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:MODE_NOT_SUPPORTED
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:MODEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     */
+    void getAllowedNetworkTypesBitmapResponse(in RadioResponseInfo info, in int networkTypeBitmap);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param bandModes List of RadioBandMode listing supported modes
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:NO_MEMORY
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:MODEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void getAvailableBandModesResponse(in RadioResponseInfo info, in RadioBandMode[] bandModes);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param networkInfos List of network operator information as OperatorInfos
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:ABORTED
+     *   RadioError:DEVICE_IN_USE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:MODEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:CANCELLED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:INTERNAL_ERR
+     */
+    void getAvailableNetworksResponse(in RadioResponseInfo info, in OperatorInfo[] networkInfos);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param cellIdentity CellIdentity for the barring infos.
+     * @param barringInfos a vector of barring info for all barring service types
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:MODEM_ERR
+     */
+    void getBarringInfoResponse(
+            in RadioResponseInfo info, in CellIdentity cellIdentity, in BarringInfo[] barringInfos);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param type CdmaRoamingType
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:NO_MEMORY
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:MODEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:SIM_ABSENT
+     */
+    void getCdmaRoamingPreferenceResponse(in RadioResponseInfo info, in CdmaRoamingType type);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param cellInfo List of current cell information known to radio
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     */
+    void getCellInfoListResponse(in RadioResponseInfo info, in CellInfo[] cellInfo);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param dataRegResponse Current data registration response as defined by RegStateResult
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NOT_PROVISIONED
+     */
+    void getDataRegistrationStateResponse(
+            in RadioResponseInfo info, in RegStateResult dataRegResponse);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param isRegistered false = not registered, true = registered
+     * @param ratFamily RadioTechnologyFamily. This value is valid only if isRegistered is true.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void getImsRegistrationStateResponse(
+            in RadioResponseInfo info, in boolean isRegistered, in RadioTechnologyFamily ratFamily);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param selection false for automatic selection, true for manual selection
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:NO_MEMORY
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:MODEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void getNetworkSelectionModeResponse(in RadioResponseInfo info, in boolean manual);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param longName is long alpha ONS or EONS or empty string if unregistered
+     * @param shortName is short alpha ONS or EONS or empty string if unregistered
+     * @param numeric is 5 or 6 digit numeric code (MCC + MNC) or empty string if unregistered
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:NO_MEMORY
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void getOperatorResponse(
+            in RadioResponseInfo info, in String longName, in String shortName, in String numeric);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param signalStrength Current signal strength
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     */
+    void getSignalStrengthResponse(in RadioResponseInfo info, in SignalStrength signalStrength);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param specifiers List of RadioAccessSpecifiers that are scanned.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     */
+    void getSystemSelectionChannelsResponse(
+            in RadioResponseInfo info, in RadioAccessSpecifier[] specifiers);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param rat Current voice RAT
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void getVoiceRadioTechnologyResponse(in RadioResponseInfo info, in RadioTechnology rat);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param voiceRegResponse Current Voice registration response as defined by RegStateResult
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     */
+    void getVoiceRegistrationStateResponse(
+            in RadioResponseInfo info, in RegStateResult voiceRegResponse);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param isEnabled Indicates whether NR dual connectivity is enabled or not, True if enabled
+     *        else false.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void isNrDualConnectivityEnabledResponse(in RadioResponseInfo info, in boolean isEnabled);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:MODE_NOT_SUPPORTED
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:MODEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     */
+    void setAllowedNetworkTypesBitmapResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:NO_MEMORY
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:MODEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void setBandModeResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:SS_MODIFIED_TO_DIAL
+     *   RadioError:SS_MODIFIED_TO_USSD
+     *   RadioError:SS_MODIFIED_TO_SS
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:NO_MEMORY
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:FDN_CHECK_FAILURE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void setBarringPasswordResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:NO_MEMORY
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:MODEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:SIM_ABSENT
+     */
+    void setCdmaRoamingPreferenceResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:NO_MEMORY
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void setCellInfoListRateResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     */
+    void setIndicationFilterResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     */
+    void setLinkCapacityReportingCriteriaResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:NO_MEMORY
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:MODEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:SIM_ABSENT
+     */
+    void setLocationUpdatesResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:ILLEGAL_SIM_OR_ME
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:NO_MEMORY
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:MODEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *
+     * Returns RadioError:ILLEGAL_SIM_OR_ME when the failure is permanent and
+     * no retries needed, such as illegal SIM or ME.
+     */
+    void setNetworkSelectionModeAutomaticResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:ILLEGAL_SIM_OR_ME
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:INVALID_STATE
+     *   RadioError:NO_MEMORY
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:MODEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *
+     * Returns RadioError:ILLEGAL_SIM_OR_ME when the failure is permanent and
+     * no retries needed, such as illegal SIM or ME.
+     */
+    void setNetworkSelectionModeManualResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:INVALID_STATE
+     */
+    void setNrDualConnectivityStateResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:RADIO_NOT_AVAILABLE
+     */
+    void setSignalStrengthReportingCriteriaResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:SIM_BUSY
+     *   RadioError:NO_MEMORY
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:SIM_ABSENT
+     */
+    void setSuppServiceNotificationsResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     */
+    void setSystemSelectionChannelsResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:DEVICE_IN_USE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:MODEM_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     */
+    void startNetworkScanResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:MODEM_ERR
+     */
+    void stopNetworkScanResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param remainingRetries Number of retries remaining, must be equal to -1 if unknown.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:PASSWORD_INCORRECT (code is invalid)
+     *   RadioError:NO_MEMORY
+     *   RadioError:INVALID_SIM_STATE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:MODEM_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:SIM_ABSENT
+     */
+    void supplyNetworkDepersonalizationResponse(in RadioResponseInfo info, in int remainingRetries);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_STATE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SIM_ABSENT
+     */
+    oneway void setUsageSettingResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error.
+     * @param usageSetting the usage setting for the current SIM.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_STATE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SIM_ABSENT
+     */
+    oneway void getUsageSettingResponse(in RadioResponseInfo info, in UsageSetting usageSetting);
+}
diff --git a/radio/aidl/android/hardware/radio/network/IndicationFilter.aidl b/radio/aidl/android/hardware/radio/network/IndicationFilter.aidl
new file mode 100644
index 0000000..9cab28d
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/IndicationFilter.aidl
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum IndicationFilter {
+    NONE = 0,
+    ALL = ~0,
+    /**
+     * When this bit is set, modem must send the signal strength update through
+     * IRadioNetworkIndication.currentSignalStrength() when all criteria specified by
+     * IRadioNetwork.setSignalStrengthReportingCriteria() are met.
+     */
+    SIGNAL_STRENGTH = 1 << 0,
+    /**
+     * When this bit is set, modem must invoke IRadioNetworkIndication.networkStateChanged() when
+     * any field in the voice or data RegStateResult changes. When this bit is not set, modem must
+     * suppress IRadioNetworkIndication.networkStateChanged() when there are only changes from
+     * insignificant fields. Modem must invoke IRadioNetworkIndication.networkStateChanged() when
+     * significant fields are updated regardless of whether this bit is set.
+     *
+     * The following fields in RegStateResult are considered significant: regState, rat.
+     */
+    FULL_NETWORK_STATE = 1 << 1,
+    /**
+     * When this bit is set, modem must send IRadioNetworkIndication.dataCallListChanged() whenever
+     * any field in SetupDataCallResult changes. When this bit is not set, modem must suppress the
+     * indication when the only changed field is 'active' (for data dormancy). For all other field
+     * changes, the modem must send IRadioNetworkIndication.dataCallListChanged() regardless of
+     * whether this bit is set.
+     */
+    DATA_CALL_DORMANCY_CHANGED = 1 << 2,
+    /**
+     * When this bit is set, modem must send the link capacity update through
+     * IRadioNetworkIndication.currentLinkCapacityEstimate() when all criteria specified by
+     * IRadioNetwork.setLinkCapacityReportingCriteria() are met.
+     */
+    LINK_CAPACITY_ESTIMATE = 1 << 3,
+    /**
+     * When this bit is set, the modem must send the physical channel configuration update through
+     * IRadioNetworkIndication.currentPhysicalChannelConfigs() when the configuration has changed.
+     * It is recommended that this be reported whenever link capacity or signal strength is
+     * reported.
+     */
+    PHYSICAL_CHANNEL_CONFIG = 1 << 4,
+    /**
+     * Control the unsolicited sending of registration failure reports via onRegistrationFailed
+     */
+    REGISTRATION_FAILURE = 1 << 5,
+    /**
+     * Control the unsolicited sending of barring info updates via onBarringInfo
+     */
+    BARRING_INFO = 1 << 6,
+}
diff --git a/radio/aidl/android/hardware/radio/network/LceDataInfo.aidl b/radio/aidl/android/hardware/radio/network/LceDataInfo.aidl
new file mode 100644
index 0000000..fdbdc2b
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/LceDataInfo.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable LceDataInfo {
+    /**
+     * Last-hop cellular capacity: kilobits/second.
+     */
+    int lastHopCapacityKbps;
+    /**
+     * Capacity estimate confidence: 0-100.
+     */
+    byte confidenceLevel;
+    /**
+     * Whether the LCE report is going to be suspended (e.g., radio moves to inactive state or
+     * network type changes).
+     */
+    boolean lceSuspended;
+}
diff --git a/radio/aidl/android/hardware/radio/network/LinkCapacityEstimate.aidl b/radio/aidl/android/hardware/radio/network/LinkCapacityEstimate.aidl
new file mode 100644
index 0000000..6461719
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/LinkCapacityEstimate.aidl
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable LinkCapacityEstimate {
+    /**
+     * Estimated downlink capacity in kbps. In case of a dual connected network, this includes
+     * capacity of both primary and secondary. This bandwidth estimate shall be the estimated
+     * maximum sustainable link bandwidth (as would be measured at the Upper PDCP or SNDCP SAP).
+     * If the DL Aggregate Maximum Bit Rate is known, this value shall not exceed the DL-AMBR for
+     * the Internet PDN connection. This must be filled with 0 if network is not connected.
+     */
+    int downlinkCapacityKbps;
+    /**
+     * Estimated uplink capacity in kbps. In case of a dual connected network, this includes
+     * capacity of both primary and secondary. This bandwidth estimate shall be the estimated
+     * maximum sustainable link bandwidth (as would be measured at the Upper PDCP or SNDCP SAP).
+     * If the UL Aggregate Maximum Bit Rate is known, this value shall not exceed the UL-AMBR for
+     * the Internet PDN connection. This must be filled with 0 if network is not connected.
+     */
+    int uplinkCapacityKbps;
+    /**
+     * Estimated downlink capacity of secondary carrier in a dual connected NR mode in kbps. This
+     * bandwidth estimate shall be the estimated maximum sustainable link bandwidth (as would be
+     * measured at the Upper PDCP or SNDCP SAP). This is valid only in if device is connected to
+     * both primary and secodary in dual connected mode. This must be filled with 0 if secondary is
+     * not connected or if modem does not support this feature.
+     */
+    int secondaryDownlinkCapacityKbps;
+    /**
+     * Estimated uplink capacity secondary carrier in a dual connected NR mode in kbps. This
+     * bandwidth estimate shall be the estimated maximum sustainable link bandwidth (as would be
+     * measured at the Upper PDCP or SNDCP SAP). This is valid only in if device is connected to
+     * both primary and secodary in dual connected mode.This must be filled with 0 if secondary is
+     * not connected or if modem does not support this feature.
+     */
+    int secondaryUplinkCapacityKbps;
+}
diff --git a/radio/aidl/android/hardware/radio/network/LteSignalStrength.aidl b/radio/aidl/android/hardware/radio/network/LteSignalStrength.aidl
new file mode 100644
index 0000000..2d97c45
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/LteSignalStrength.aidl
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable LteSignalStrength {
+    /**
+     * Valid values are (0-31, 99) as defined in TS 27.007 8.5; INT_MAX means invalid/unreported.
+     */
+    int signalStrength;
+    /**
+     * The current Reference Signal Receive Power in dBm multiplied by -1. Range: 44 to 140 dBm;
+     * INT_MAX: 0x7FFFFFFF denotes invalid/unreported value. Reference: 3GPP TS 36.133 9.1.4
+     */
+    int rsrp;
+    /**
+     * The current Reference Signal Receive Quality in dB multiplied by -1. Range: 20 to 3 dB;
+     * INT_MAX: 0x7FFFFFFF denotes invalid/unreported value. Reference: 3GPP TS 36.133 9.1.7
+     */
+    int rsrq;
+    /**
+     * The current reference signal signal-to-noise ratio in 0.1 dB units.
+     * Range: -200 to +300 (-200 = -20.0 dB, +300 = 30dB).
+     * INT_MAX: 0x7FFFFFFF denotes invalid/unreported value. Reference: 3GPP TS 36.101 8.1.1
+     */
+    int rssnr;
+    /**
+     * The current Channel Quality Indicator. Range: 0 to 15.
+     * INT_MAX: 0x7FFFFFFF denotes invalid/unreported value. Reference: 3GPP TS 36.101 9.2, 9.3, A.4
+     */
+    int cqi;
+    /**
+     * Timing advance in micro seconds for a one way trip from cell to device. Approximate distance
+     * is calculated using 300m/us * timingAdvance. Range: 0 to 1282 inclusive.
+     * INT_MAX: 0x7FFFFFFF denotes invalid/unreported value. Reference: 3GPP 36.213 section 4.2.3
+     */
+    int timingAdvance;
+    /**
+     * CSI channel quality indicator (CQI) table index. There are multiple CQI tables.
+     * The definition of CQI in each table is different.
+     * Reference: 3GPP TS 136.213 section 7.2.3.
+     * Range [1, 6], INT_MAX means invalid/unreported.
+     */
+    int cqiTableIndex;
+}
diff --git a/radio/aidl/android/hardware/radio/network/LteVopsInfo.aidl b/radio/aidl/android/hardware/radio/network/LteVopsInfo.aidl
new file mode 100644
index 0000000..fb3b986
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/LteVopsInfo.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+/**
+ * Type to define the LTE specific network capabilities for voice over PS including emergency and
+ * normal voice calls.
+ */
+@VintfStability
+@JavaDerive(toString=true)
+parcelable LteVopsInfo {
+    /**
+     * This indicates if camped network support VoLTE services. This information is received from
+     * LTE network during LTE NAS registration procedure through LTE ATTACH ACCEPT/TAU ACCEPT.
+     * Refer 3GPP 24.301 EPS network feature support -> IMS VoPS
+     */
+    boolean isVopsSupported;
+    /**
+     * This indicates if camped network support VoLTE emergency bearers. This information is
+     * received from LTE network through two sources:
+     * a. During LTE NAS registration procedure through LTE ATTACH ACCEPT/TAU ACCEPT. Refer
+     *    3GPP 24.301 EPS network feature support -> EMC BS
+     * b. In case device is not registered on network. Refer 3GPP 25.331 LTE RRC
+     *    SIB1 : ims-EmergencySupport-r9
+     * If device is registered on LTE, then this field indicates (a).
+     * In case of limited service on LTE this field indicates (b).
+     */
+    boolean isEmcBearerSupported;
+}
diff --git a/radio/aidl/android/hardware/radio/network/NetworkScanRequest.aidl b/radio/aidl/android/hardware/radio/network/NetworkScanRequest.aidl
new file mode 100644
index 0000000..ae173c7
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/NetworkScanRequest.aidl
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+import android.hardware.radio.network.RadioAccessSpecifier;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable NetworkScanRequest {
+    const int RADIO_ACCESS_SPECIFIER_MAX_SIZE = 8;
+
+    const int INCREMENTAL_RESULTS_PREIODICITY_RANGE_MIN = 1;
+    const int INCREMENTAL_RESULTS_PREIODICITY_RANGE_MAX = 10;
+
+    const int MAX_SEARCH_TIME_RANGE_MIN = 60;
+    const int MAX_SEARCH_TIME_RANGE_MAX = 3600;
+
+    const int SCAN_INTERVAL_RANGE_MIN = 5;
+    const int SCAN_INTERVAL_RANGE_MAX = 300;
+
+    /**
+     * Performs the scan only once
+     */
+    const int SCAN_TYPE_ONE_SHOT = 0;
+    /**
+     * Performs the scan periodically until cancelled
+     */
+    const int SCAN_TYPE_PERIODIC = 1;
+
+    /**
+     * Values are SCAN_TYPE_
+     */
+    int type;
+    /**
+     * Time interval in seconds between the completion of one scan and the start of a subsequent
+     * scan. Implementations may ignore this field unless the 'type' is 'PERIODIC'.
+     * Range: SCAN_INTERVAL_RANGE_MIN to SCAN_INTERVAL_RANGE_MAX.
+     */
+    int interval;
+    /**
+     * Networks with bands/channels to scan.
+     * Maximum length of the vector is RADIO_ACCESS_SPECIFIER_MAX_SIZE.
+     */
+    RadioAccessSpecifier[] specifiers;
+    /**
+     * Maximum duration of the periodic search (in seconds). If the search lasts maxSearchTime, it
+     * must be terminated. Range: MAX_SEARCH_TIME_RANGE_MIN to MAX_SEARCH_TIME_RANGE_MAX
+     */
+    int maxSearchTime;
+    /**
+     * Whether the modem must report incremental results of the network scan to the client.
+     * FALSE – Incremental results must not be reported.
+     * TRUE  – Incremental must be reported.
+     */
+    boolean incrementalResults;
+    /**
+     * Indicates the periodicity with which the modem must report incremental results to the client
+     * (in seconds). Implementations may ignore this value if the incremental results are not
+     * requested. This value must be less than or equal to maxSearchTime.
+     * Range: INCREMENTAL_RESULTS_PREIODICITY_RANGE_MIN to INCREMENTAL_RESULTS_PREIODICITY_RANGE_MAX
+     */
+    int incrementalResultsPeriodicity;
+    /**
+     * Describes the List of PLMN ids (MCC-MNC). If any PLMN of this list is found, search must end
+     * at that point and results with all PLMN found until that point should be sent as response.
+     * If the list is not sent, search to be completed until end and all PLMNs found to be reported.
+     */
+    String[] mccMncs;
+}
diff --git a/radio/aidl/android/hardware/radio/network/NetworkScanResult.aidl b/radio/aidl/android/hardware/radio/network/NetworkScanResult.aidl
new file mode 100644
index 0000000..6d83f74
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/NetworkScanResult.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+import android.hardware.radio.RadioError;
+import android.hardware.radio.network.CellInfo;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable NetworkScanResult {
+    /**
+     * The result contains a part of the scan results.
+     */
+    const int SCAN_STATUS_PARTIAL = 1;
+    /**
+     * The result contains the last part of the scan results.
+     */
+    const int SCAN_STATUS_COMPLETE = 2;
+
+    /**
+     * The status of the scan.
+     * Values are SCAN_STATUS_
+     */
+    int status;
+    /**
+     * The error code of the incremental result.
+     */
+    RadioError error;
+    /**
+     * List of network information as CellInfo.
+     */
+    CellInfo[] networkInfos;
+}
diff --git a/radio/aidl/android/hardware/radio/network/NgranBands.aidl b/radio/aidl/android/hardware/radio/network/NgranBands.aidl
new file mode 100644
index 0000000..53c7a3d
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/NgranBands.aidl
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+/**
+ * NGRAN bands up to V16.5.0
+ */
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum NgranBands {
+    /**
+     * 3GPP TS 38.101-1, Table 5.2-1: FR1 bands
+     */
+    BAND_1 = 1,
+    BAND_2 = 2,
+    BAND_3 = 3,
+    BAND_5 = 5,
+    BAND_7 = 7,
+    BAND_8 = 8,
+    BAND_12 = 12,
+    BAND_14 = 14,
+    BAND_18 = 18,
+    BAND_20 = 20,
+    BAND_25 = 25,
+    BAND_26 = 26,
+    BAND_28 = 28,
+    BAND_29 = 29,
+    BAND_30 = 30,
+    BAND_34 = 34,
+    BAND_38 = 38,
+    BAND_39 = 39,
+    BAND_40 = 40,
+    BAND_41 = 41,
+    BAND_46 = 46,
+    BAND_48 = 48,
+    BAND_50 = 50,
+    BAND_51 = 51,
+    BAND_53 = 53,
+    BAND_65 = 65,
+    BAND_66 = 66,
+    BAND_70 = 70,
+    BAND_71 = 71,
+    BAND_74 = 74,
+    BAND_75 = 75,
+    BAND_76 = 76,
+    BAND_77 = 77,
+    BAND_78 = 78,
+    BAND_79 = 79,
+    BAND_80 = 80,
+    BAND_81 = 81,
+    BAND_82 = 82,
+    BAND_83 = 83,
+    BAND_84 = 84,
+    BAND_86 = 86,
+    BAND_89 = 89,
+    BAND_90 = 90,
+    BAND_91 = 91,
+    BAND_92 = 92,
+    BAND_93 = 93,
+    BAND_94 = 94,
+    BAND_95 = 95,
+    BAND_96 = 96,
+    /**
+     * 3GPP TS 38.101-2, Table 5.2-1: FR2 bands
+     */
+    BAND_257 = 257,
+    BAND_258 = 258,
+    BAND_260 = 260,
+    BAND_261 = 261,
+}
diff --git a/radio/aidl/android/hardware/radio/network/NrDualConnectivityState.aidl b/radio/aidl/android/hardware/radio/network/NrDualConnectivityState.aidl
new file mode 100644
index 0000000..e293dff
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/NrDualConnectivityState.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+/**
+ * NR Dual connectivity state
+ */
+@VintfStability
+@Backing(type="byte")
+@JavaDerive(toString=true)
+enum NrDualConnectivityState {
+    /**
+     * Enable NR dual connectivity. Enabled state does not mean dual connectivity is active.
+     * It means device is allowed to connect to both primary and secondary.
+     */
+    ENABLE = 1,
+    /**
+     * Disable NR dual connectivity. Disabled state does not mean secondary cell is released.
+     * Modem will release it only if current bearer is released to avoid radio link failure.
+     */
+    DISABLE = 2,
+    /**
+     * Disable NR dual connectivity and force secondary cell to be released if dual connectivity
+     * was active. This may result in radio link failure.
+     */
+    DISABLE_IMMEDIATE = 3,
+}
diff --git a/radio/aidl/android/hardware/radio/network/NrIndicators.aidl b/radio/aidl/android/hardware/radio/network/NrIndicators.aidl
new file mode 100644
index 0000000..32cc964
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/NrIndicators.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+/**
+ * The parameters of NR 5G Non-Standalone.
+ */
+@VintfStability
+@JavaDerive(toString=true)
+parcelable NrIndicators {
+    /**
+     * Indicates that if E-UTRA-NR Dual Connectivity (EN-DC) is supported by the primary serving
+     * cell. True the primary serving cell is LTE cell and the plmn-InfoList-r15 is present in SIB2
+     * and at least one bit in this list is true, otherwise this value should be false.
+     * Reference: 3GPP TS 36.331 v15.2.2 6.3.1 System information blocks.
+     */
+    boolean isEndcAvailable;
+    /**
+     * True if use of dual connectivity with NR is restricted.
+     * Reference: 3GPP TS 24.301 v15.03 section 9.3.3.12A.
+     */
+    boolean isDcNrRestricted;
+    /**
+     * True if the bit N is in the PLMN-InfoList-r15 is true and the selected PLMN is present in
+     * plmn-IdentityList at position N.
+     * Reference: 3GPP TS 36.331 v15.2.2 section 6.3.1 PLMN-InfoList-r15.
+     *            3GPP TS 36.331 v15.2.2 section 6.2.2 SystemInformationBlockType1 message.
+     */
+    boolean isNrAvailable;
+}
diff --git a/radio/aidl/android/hardware/radio/network/NrSignalStrength.aidl b/radio/aidl/android/hardware/radio/network/NrSignalStrength.aidl
new file mode 100644
index 0000000..1bb569a
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/NrSignalStrength.aidl
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable NrSignalStrength {
+    /**
+     * SS reference signal received power, multiplied by -1.
+     * Reference: 3GPP TS 38.215.
+     * Range [44, 140], INT_MAX means invalid/unreported.
+     */
+    int ssRsrp;
+    /**
+     * SS reference signal received quality, multiplied by -1.
+     * Reference: 3GPP TS 38.215, 3GPP TS 38.133 section 10.
+     * Range [-20 dB, 43 dB], INT_MAX means invalid/unreported.
+     */
+    int ssRsrq;
+    /**
+     * SS signal-to-noise and interference ratio.
+     * Reference: 3GPP TS 38.215 section 5.1.*, 3GPP TS 38.133 section 10.1.16.1.
+     * Range [-23, 40], INT_MAX means invalid/unreported.
+     */
+    int ssSinr;
+    /**
+     * CSI reference signal received power, multiplied by -1.
+     * Reference: 3GPP TS 38.215.
+     * Range [44, 140], INT_MAX means invalid/unreported.
+     */
+    int csiRsrp;
+    /**
+     * CSI reference signal received quality, multiplied by -1.
+     * Reference: 3GPP TS 38.215.
+     * Range [3, 20], INT_MAX means invalid/unreported.
+     */
+    int csiRsrq;
+    /**
+     * CSI signal-to-noise and interference ratio.
+     * Reference: 3GPP TS 138.215 section 5.1.*, 3GPP TS 38.133 section 10.1.16.1.
+     * Range [-23, 40], INT_MAX means invalid/unreported.
+     */
+    int csiSinr;
+    /**
+     * CSI channel quality indicator (CQI) table index. There are multiple CQI tables.
+     * The definition of CQI in each table is different.
+     * Reference: 3GPP TS 138.214 section 5.2.2.1.
+     * Range [1, 3], INT_MAX means invalid/unreported.
+     */
+    int csiCqiTableIndex;
+    /**
+     * CSI channel quality indicator (CQI) for all subbands. If the CQI report is for the entire
+     * wideband, a single CQI index is provided. If the CQI report is for all subbands, one CQI
+     * index is provided for each subband, in ascending order of subband index. If CQI is not
+     * available, the CQI report is empty.
+     * Reference: 3GPP TS 138.214 section 5.2.2.1.
+     * Range [0, 15], 0xFF means invalid/unreported.
+     */
+    byte[] csiCqiReport;
+}
diff --git a/radio/aidl/android/hardware/radio/network/NrVopsInfo.aidl b/radio/aidl/android/hardware/radio/network/NrVopsInfo.aidl
new file mode 100644
index 0000000..197f401
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/NrVopsInfo.aidl
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+/**
+ * Type to define the NR specific network capabilities for voice over PS including emergency and
+ * normal voice calls.
+ */
+@VintfStability
+@JavaDerive(toString=true)
+parcelable NrVopsInfo {
+    /**
+     * Emergency services not supported
+     */
+    const byte EMC_INDICATOR_NOT_SUPPORTED = 0;
+    /**
+     * Emergency services supported in NR connected to 5GCN only
+     */
+    const byte EMC_INDICATOR_NR_CONNECTED_TO_5GCN = 1;
+    /**
+     * Emergency services supported in E-UTRA connected to 5GCN only
+     */
+    const byte EMC_INDICATOR_EUTRA_CONNECTED_TO_5GCN = 2;
+    /**
+     * Emergency services supported in NR connected to 5GCN and E-UTRA connected to 5GCN
+     */
+    const byte EMC_INDICATOR_BOTH_NR_EUTRA_CONNECTED_TO_5GCN = 3;
+
+    /**
+     * Emergency services fallback not supported
+     */
+    const byte EMF_INDICATOR_NOT_SUPPORTED = 0;
+    /**
+     * Emergency services fallback supported in NR connected to 5GCN only
+     */
+    const byte EMF_INDICATOR_NR_CONNECTED_TO_5GCN = 1;
+    /**
+     * Emergency services fallback supported in E-UTRA connected to 5GCN only
+     */
+    const byte EMF_INDICATOR_EUTRA_CONNECTED_TO_5GCN = 2;
+    /**
+     * Emergency services fallback supported in NR connected to 5GCN and E-UTRA connected to 5GCN.
+     */
+    const byte EMF_INDICATOR_BOTH_NR_EUTRA_CONNECTED_TO_5GCN = 3;
+
+    /**
+     * IMS voice over PS session not supported
+     */
+    const byte VOPS_INDICATOR_VOPS_NOT_SUPPORTED = 0;
+    /**
+     * IMS voice over PS session supported over 3GPP access
+     */
+    const byte VOPS_INDICATOR_VOPS_OVER_3GPP = 1;
+    /**
+     * IMS voice over PS session supported over non-3GPP access
+     */
+    const byte VOPS_INDICATOR_VOPS_OVER_NON_3GPP = 2;
+
+    /**
+     * This indicates if the camped network supports VoNR services, and what kind of services
+     * it supports. This information is received from NR network during NR NAS registration
+     * procedure through NR REGISTRATION ACCEPT.
+     * Refer 3GPP 24.501 EPS 5GS network feature support -> IMS VoPS
+     * Values are VOPS_INDICATOR_
+     */
+    byte vopsSupported;
+    /**
+     * This indicates if the camped network supports VoNR emergency service. This information
+     * is received from NR network through two sources:
+     * a. During NR NAS registration procedure through NR REGISTRATION ACCEPT.
+     *    Refer 3GPP 24.501 EPS 5GS network feature support -> EMC
+     * b. In case the device is not registered on the network.
+     *    Refer 3GPP 38.331 SIB1 : ims-EmergencySupport
+     *    If device is registered on NR, then this field indicates whether the cell
+     *    supports IMS emergency bearer services for UEs in limited service mode.
+     * Values are EMC_INDICATOR_
+     */
+    byte emcSupported;
+    /**
+     * This indicates if the camped network supports VoNR emergency service fallback. This
+     * information is received from NR network during NR NAS registration procedure through
+     * NR REGISTRATION ACCEPT.
+     * Refer 3GPP 24.501 EPS 5GS network feature support -> EMF
+     * Values are EMF_INDICATOR_ from TS 24.501 sec 9.10.3.5.
+     */
+    byte emfSupported;
+}
diff --git a/radio/aidl/android/hardware/radio/network/OperatorInfo.aidl b/radio/aidl/android/hardware/radio/network/OperatorInfo.aidl
new file mode 100644
index 0000000..56f4dca
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/OperatorInfo.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable OperatorInfo {
+    const int STATUS_UNKNOWN = 0;
+    const int STATUS_AVAILABLE = 1;
+    const int STATUS_CURRENT = 2;
+    const int STATUS_FORBIDDEN = 3;
+
+    /**
+     * Long alpha ONS or EONS
+     */
+    String alphaLong;
+    /**
+     * Short alpha ONS or EONS
+     */
+    String alphaShort;
+    /**
+     * 5 or 6 digit numeric code (MCC + MNC)
+     */
+    String operatorNumeric;
+    /**
+     * Values are STATUS_
+     */
+    int status;
+}
diff --git a/radio/aidl/android/hardware/radio/network/PhoneRestrictedState.aidl b/radio/aidl/android/hardware/radio/network/PhoneRestrictedState.aidl
new file mode 100644
index 0000000..23ae3b1
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/PhoneRestrictedState.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum PhoneRestrictedState {
+    /**
+     * No restriction at all including voice/SMS/USSD/SS/AV64 and packet data.
+     */
+    NONE = 0x00,
+    /**
+     * Block emergency call due to restriction. But allow all normal voice/SMS/USSD/SS/AV64.
+     */
+    CS_EMERGENCY = 0x01,
+    /**
+     * Block all normal voice/SMS/USSD/SS/AV64 due to restriction. Only Emergency call allowed.
+     */
+    CS_NORMAL = 0x02,
+    /**
+     * Block all voice/SMS/USSD/SS/AV64 including emergency call due to restriction.
+     */
+    CS_ALL = 0x04,
+    /**
+     * Block packet data access due to restriction.
+     */
+    PS_ALL = 0x10,
+}
diff --git a/radio/aidl/android/hardware/radio/network/PhysicalChannelConfig.aidl b/radio/aidl/android/hardware/radio/network/PhysicalChannelConfig.aidl
new file mode 100644
index 0000000..9996953
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/PhysicalChannelConfig.aidl
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+import android.hardware.radio.RadioTechnology;
+import android.hardware.radio.network.CellConnectionStatus;
+import android.hardware.radio.network.PhysicalChannelConfigBand;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable PhysicalChannelConfig {
+    /**
+     * Connection status for cell. Valid values are PRIMARY_SERVING and SECONDARY_SERVING
+     */
+    CellConnectionStatus status;
+    /**
+     * The radio technology for this physical channel
+     */
+    RadioTechnology rat;
+    /**
+     * Downlink Absolute Radio Frequency Channel Number
+     */
+    int downlinkChannelNumber;
+    /**
+     * Uplink Absolute Radio Frequency Channel Number
+     */
+    int uplinkChannelNumber;
+    /**
+     * Downlink cell bandwidth, in kHz
+     */
+    int cellBandwidthDownlinkKhz;
+    /**
+     * Uplink cell bandwidth, in kHz
+     */
+    int cellBandwidthUplinkKhz;
+    /**
+     * A list of data calls mapped to this physical channel. The context id must match the cid of
+     * SetupDataCallResult. An empty list means the physical channel has no data call mapped to it.
+     */
+    int[] contextIds;
+    /**
+     * The physical cell identifier for this cell.
+     * In UTRAN, this value is primary scrambling code. The range is [0, 511].
+     * Reference: 3GPP TS 25.213 section 5.2.2.
+     * In EUTRAN, this value is physical layer cell identity. The range is [0, 503].
+     * Reference: 3GPP TS 36.211 section 6.11.
+     * In NGRAN, this value is physical layer cell identity. The range is [0, 1007].
+     * Reference: 3GPP TS 38.211 section 7.4.2.1.
+     */
+    int physicalCellId;
+    /**
+     * The frequency band to scan.
+     */
+    PhysicalChannelConfigBand band;
+}
diff --git a/radio/aidl/android/hardware/radio/network/PhysicalChannelConfigBand.aidl b/radio/aidl/android/hardware/radio/network/PhysicalChannelConfigBand.aidl
new file mode 100644
index 0000000..707a032
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/PhysicalChannelConfigBand.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+import android.hardware.radio.network.EutranBands;
+import android.hardware.radio.network.GeranBands;
+import android.hardware.radio.network.NgranBands;
+import android.hardware.radio.network.UtranBands;
+
+@VintfStability
+@JavaDerive(toString=true)
+union PhysicalChannelConfigBand {
+    boolean noinit;
+    /**
+     * Valid only if radioAccessNetwork = GERAN.
+     */
+    GeranBands geranBand;
+    /**
+     * Valid only if radioAccessNetwork = UTRAN.
+     */
+    UtranBands utranBand;
+    /**
+     * Valid only if radioAccessNetwork = EUTRAN.
+     */
+    EutranBands eutranBand;
+    /**
+     * Valid only if radioAccessNetwork = NGRAN.
+     */
+    NgranBands ngranBand;
+}
diff --git a/radio/aidl/android/hardware/radio/network/RadioAccessSpecifier.aidl b/radio/aidl/android/hardware/radio/network/RadioAccessSpecifier.aidl
new file mode 100644
index 0000000..8504248
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/RadioAccessSpecifier.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+import android.hardware.radio.AccessNetwork;
+import android.hardware.radio.network.RadioAccessSpecifierBands;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable RadioAccessSpecifier {
+    /**
+     * The type of network to scan.
+     */
+    AccessNetwork accessNetwork;
+    /**
+     * The frequency bands to scan. Maximum length of the vector is 8.
+     */
+    RadioAccessSpecifierBands bands;
+    /**
+     * The radio channels to scan as defined in 3GPP TS 25.101 and 36.101.
+     * Maximum length of the vector is 32.
+     */
+    int[] channels;
+}
diff --git a/radio/aidl/android/hardware/radio/network/RadioAccessSpecifierBands.aidl b/radio/aidl/android/hardware/radio/network/RadioAccessSpecifierBands.aidl
new file mode 100644
index 0000000..38afee5
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/RadioAccessSpecifierBands.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+import android.hardware.radio.network.EutranBands;
+import android.hardware.radio.network.GeranBands;
+import android.hardware.radio.network.NgranBands;
+import android.hardware.radio.network.UtranBands;
+
+@VintfStability
+@JavaDerive(toString=true)
+union RadioAccessSpecifierBands {
+    boolean noinit;
+    /**
+     * Valid only if radioAccessNetwork = GERAN.
+     */
+    GeranBands[] geranBands;
+    /**
+     * Valid only if radioAccessNetwork = UTRAN.
+     */
+    UtranBands[] utranBands;
+    /**
+     * Valid only if radioAccessNetwork = EUTRAN.
+     */
+    EutranBands[] eutranBands;
+    /**
+     * Valid only if radioAccessNetwork = NGRAN.
+     */
+    NgranBands[] ngranBands;
+}
diff --git a/radio/aidl/android/hardware/radio/network/RadioBandMode.aidl b/radio/aidl/android/hardware/radio/network/RadioBandMode.aidl
new file mode 100644
index 0000000..45c4a51
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/RadioBandMode.aidl
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum RadioBandMode {
+    /**
+     * "Unspecified" (selected by baseband automatically)
+     */
+    BAND_MODE_UNSPECIFIED,
+    /**
+     * "EURO band" (GSM-900 / DCS-1800 / WCDMA-IMT-2000)
+     */
+    BAND_MODE_EURO,
+    /**
+     * "US band" (GSM-850 / PCS-1900 / WCDMA-850 / WCDMA-PCS-1900)
+     */
+    BAND_MODE_USA,
+    /**
+     * "JPN band" (WCDMA-800 / WCDMA-IMT-2000)
+     */
+    BAND_MODE_JPN,
+    /**
+     * "AUS band" (GSM-900 / DCS-1800 / WCDMA-850 / WCDMA-IMT-2000)
+     */
+    BAND_MODE_AUS,
+    /**
+     * "AUS band 2" (GSM-900 / DCS-1800 / WCDMA-850)
+     */
+    BAND_MODE_AUS_2,
+    /**
+     * "Cellular" (800-MHz Band)
+     */
+    BAND_MODE_CELL_800,
+    /**
+     * "PCS" (1900-MHz Band)
+     */
+    BAND_MODE_PCS,
+    /**
+     * "Band Class 3" (JTACS Band)
+     */
+    BAND_MODE_JTACS,
+    /**
+     * "Band Class 4" (Korean PCS Band)
+     */
+    BAND_MODE_KOREA_PCS,
+    /**
+     * "Band Class 5" (450-MHz Band)
+     */
+    BAND_MODE_5_450M,
+    /**
+     * "Band Class 6" (2-GMHz IMT2000 Band)
+     */
+    BAND_MODE_IMT2000,
+    /**
+     * "Band Class 7" (Upper 700-MHz Band)
+     */
+    BAND_MODE_7_700M_2,
+    /**
+     * "Band Class 8" (1800-MHz Band)
+     */
+    BAND_MODE_8_1800M,
+    /**
+     * "Band Class 9" (900-MHz Band)
+     */
+    BAND_MODE_9_900M,
+    /**
+     * "Band Class 10" (Secondary 800-MHz Band)
+     */
+    BAND_MODE_10_800M_2,
+    /**
+     * "Band Class 11" (400-MHz European PAMR Band)
+     */
+    BAND_MODE_EURO_PAMR_400M,
+    /**
+     * "Band Class 15" (AWS Band)
+     */
+    BAND_MODE_AWS,
+    /**
+     * "Band Class 16" (US 2.5-GHz Band)
+     */
+    BAND_MODE_USA_2500M,
+}
diff --git a/radio/aidl/android/hardware/radio/network/RegState.aidl b/radio/aidl/android/hardware/radio/network/RegState.aidl
new file mode 100644
index 0000000..3f13783
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/RegState.aidl
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+/**
+ * Please note that registration state UNKNOWN is treated as "out of service" in Android telephony.
+ * Registration state REG_DENIED must be returned if Location Update Reject (with cause 17 - Network
+ * Failure) is received repeatedly from the network, to facilitate "managed roaming".
+ */
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum RegState {
+    /**
+     * Not registered, MT is not currently searching for a new operator to register
+     */
+    NOT_REG_MT_NOT_SEARCHING_OP = 0,
+    /**
+     * Registered, home network
+     */
+    REG_HOME = 1,
+    /**
+     * Not registered, but MT is currently searching for a new operator to register
+     */
+    NOT_REG_MT_SEARCHING_OP = 2,
+    /**
+     * Registration denied
+     */
+    REG_DENIED = 3,
+    /**
+     * Unknown
+     */
+    UNKNOWN = 4,
+    /**
+     * Registered, roaming
+     */
+    REG_ROAMING = 5,
+    /**
+     * Same as NOT_REG_MT_NOT_SEARCHING_OP but indicates that emergency calls are enabled
+     */
+    NOT_REG_MT_NOT_SEARCHING_OP_EM = 10,
+    /**
+     * Same as NOT_REG_MT_SEARCHING_OP but indicatees that emergency calls are enabled
+     */
+    NOT_REG_MT_SEARCHING_OP_EM = 12,
+    /**
+     * Same as REG_DENIED but indicates that emergency calls are enabled
+     */
+    REG_DENIED_EM = 13,
+    /**
+     * Same as UNKNOWN but indicates that emergency calls are enabled
+     */
+    UNKNOWN_EM = 14,
+}
diff --git a/radio/aidl/android/hardware/radio/network/RegStateResult.aidl b/radio/aidl/android/hardware/radio/network/RegStateResult.aidl
new file mode 100644
index 0000000..3d96b8c
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/RegStateResult.aidl
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+import android.hardware.radio.RadioTechnology;
+import android.hardware.radio.network.AccessTechnologySpecificInfo;
+import android.hardware.radio.network.CellIdentity;
+import android.hardware.radio.network.RegState;
+import android.hardware.radio.network.RegistrationFailCause;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable RegStateResult {
+    /**
+     * Registration state. If the RAT is indicated as a GERAN, UTRAN, or CDMA2000 technology, this
+     * value reports registration in the Circuit-switched domain. If the RAT is indicated as an
+     * EUTRAN, NGRAN, or another technology that does not support circuit-switched services, this
+     * value reports registration in the Packet-switched domain.
+     */
+    RegState regState;
+    /**
+     * Indicates the radio technology (except LTE_CA, which is no longer a valid value), which
+     * must not be UNKNOWN if regState is REG_HOME, REG_ROAMING, NOT_REG_MT_NOT_SEARCHING_OP_EM,
+     * NOT_REG_MT_SEARCHING_OP_EM, REG_DENIED_EM, or UNKNOWN_EM.
+     * When the device is on carrier aggregation, vendor RIL service must properly report multiple
+     * PhysicalChannelConfig elements through IRadioNetwork::currentPhysicalChannelConfigs.
+     */
+    RadioTechnology rat;
+    /**
+     * Cause code reported by the network in case registration fails. This will be a mobility
+     * management cause code defined for MM, GMM, MME or equivalent as appropriate for the RAT.
+     */
+    RegistrationFailCause reasonForDenial;
+    /**
+     * CellIdentity
+     */
+    CellIdentity cellIdentity;
+    /**
+     * The most-recent PLMN-ID upon which the UE registered (or attempted to register if a failure
+     * is reported in the reasonForDenial field). This PLMN shall be in standard format consisting
+     * of a 3 digit MCC concatenated with a 2 or 3 digit MNC.
+     */
+    String registeredPlmn;
+    /**
+     * Access-technology-specific registration information, such as for CDMA2000.
+     */
+    AccessTechnologySpecificInfo accessTechnologySpecificInfo;
+}
diff --git a/radio/aidl/android/hardware/radio/network/RegistrationFailCause.aidl b/radio/aidl/android/hardware/radio/network/RegistrationFailCause.aidl
new file mode 100644
index 0000000..9549f2e
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/RegistrationFailCause.aidl
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+/**
+ * Call fail causes for Circuit-switched service enumerated in 3GPP TS 24.008, 10.5.3.6 and
+ * 10.5.147. Additional detail is available in 3GPP TS 24.008 Annex G.
+ */
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum RegistrationFailCause {
+    /**
+     * 0 - None
+     */
+    NONE = 0,
+    /**
+     * 2 - IMSI unknown in HLR
+     */
+    IMSI_UNKNOWN_IN_HLR = 2,
+    /**
+     * 3 - Illegal MS
+     */
+    ILLEGAL_MS = 3,
+    /**
+     * 4 - Illegal ME
+     */
+    IMSI_UNKNOWN_IN_VLR = 4,
+    /**
+     * 5 - PLMN not allowed
+     */
+    IMEI_NOT_ACCEPTED = 5,
+    /**
+     * 6 - Location area not allowed
+     */
+    ILLEGAL_ME = 6,
+    /**
+     * 7 - Roaming not allowed
+     */
+    GPRS_SERVICES_NOT_ALLOWED = 7,
+    /**
+     * 8 - No Suitable Cells in this Location Area
+     */
+    GPRS_AND_NON_GPRS_SERVICES_NOT_ALLOWED = 8,
+    /**
+     * 9 - Network failure
+     */
+    MS_IDENTITY_CANNOT_BE_DERIVED_BY_NETWORK = 9,
+    /**
+     * 10 - Persistent location update reject
+     */
+    IMPLICITLY_DETACHED = 10,
+    /**
+     * 11 - PLMN not allowed
+     */
+    PLMN_NOT_ALLOWED = 11,
+    /**
+     * 12 - Location area not allowed
+     */
+    LOCATION_AREA_NOT_ALLOWED = 12,
+    /**
+     * 13 - Roaming not allowed in this Location Area
+     */
+    ROAMING_NOT_ALLOWED = 13,
+    /**
+     * 14 - GPRS Services not allowed in this PLMN
+     */
+    GPRS_SERVICES_NOT_ALLOWED_IN_PLMN = 14,
+    /**
+     * 15 - No Suitable Cells in this Location Area
+     */
+    NO_SUITABLE_CELLS = 15,
+    /**
+     * 16 - MSC temporarily not reachable
+     */
+    MSC_TEMPORARILY_NOT_REACHABLE = 15,
+    /**
+     * 17 - Network Failure
+     */
+    NETWORK_FAILURE = 17,
+    /**
+     * 20 - MAC Failure
+     */
+    MAC_FAILURE = 20,
+    /**
+     * 21 - Sync Failure
+     */
+    SYNC_FAILURE = 21,
+    /**
+     * 22 - Congestion
+     */
+    CONGESTION = 22,
+    /**
+     * 23 - GSM Authentication unacceptable
+     */
+    GSM_AUTHENTICATION_UNACCEPTABLE = 23,
+    /**
+     * 25 - Not Authorized for this CSG
+     */
+    NOT_AUTHORIZED_FOR_THIS_CSG = 25,
+    /**
+     * 28 SMS provided via GPRS in this routing area
+     */
+    SMS_PROVIDED_BY_GPRS_IN_ROUTING_AREA,
+    /**
+     * 32 - Service option not supported
+     */
+    SERVICE_OPTION_NOT_SUPPORTED = 32,
+    /**
+     * 33 - Requested service option not subscribed
+     */
+    SERVICE_OPTION_NOT_SUBSCRIBED = 33,
+    /**
+     * 34 - Service option temporarily out of order
+     */
+    SERVICE_OPTION_TEMPORARILY_OUT_OF_ORDER = 34,
+    /**
+     * 38 - Call cannot be identified
+     */
+    CALL_CANNOT_BE_IDENTIFIED = 38,
+    /**
+     * 40 No PDP context activated
+     */
+    NO_PDP_CONTEXT_ACTIVATED = 40,
+    /**
+     * 48-63 - Retry upon entry into a new cell
+     */
+    RETRY_UPON_ENTRY_INTO_NEW_CELL_1 = 48,
+    RETRY_UPON_ENTRY_INTO_NEW_CELL_2 = 49,
+    RETRY_UPON_ENTRY_INTO_NEW_CELL_3 = 50,
+    RETRY_UPON_ENTRY_INTO_NEW_CELL_4 = 51,
+    RETRY_UPON_ENTRY_INTO_NEW_CELL_5 = 52,
+    RETRY_UPON_ENTRY_INTO_NEW_CELL_6 = 53,
+    RETRY_UPON_ENTRY_INTO_NEW_CELL_7 = 54,
+    RETRY_UPON_ENTRY_INTO_NEW_CELL_8 = 55,
+    RETRY_UPON_ENTRY_INTO_NEW_CELL_9 = 56,
+    RETRY_UPON_ENTRY_INTO_NEW_CELL_10 = 57,
+    RETRY_UPON_ENTRY_INTO_NEW_CELL_11 = 58,
+    RETRY_UPON_ENTRY_INTO_NEW_CELL_12 = 59,
+    RETRY_UPON_ENTRY_INTO_NEW_CELL_13 = 60,
+    RETRY_UPON_ENTRY_INTO_NEW_CELL_14 = 61,
+    RETRY_UPON_ENTRY_INTO_NEW_CELL_15 = 62,
+    RETRY_UPON_ENTRY_INTO_NEW_CELL_16 = 63,
+    /**
+     * 95 - Semantically incorrect message
+     */
+    SEMANTICALLY_INCORRECT_MESSAGE = 95,
+    /**
+     * 96 - Invalid mandatory information
+     */
+    INVALID_MANDATORY_INFORMATION = 96,
+    /**
+     * 97 - Message type non-existent or not implemented
+     */
+    MESSAGE_TYPE_NON_EXISTENT_OR_NOT_IMPLEMENTED = 97,
+    /**
+     * 98 - Message type not compatible with protocol state
+     */
+    MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 98,
+    /**
+     * 99 - Information element non-existent or not implemented
+     */
+    INFORMATION_ELEMENT_NON_EXISTENT_OR_NOT_IMPLEMENTED = 99,
+    /**
+     * 100 - Conditional IE error
+     */
+    CONDITIONAL_IE_ERROR = 100,
+    /**
+     * 101 - Message not compatible with protocol state
+     */
+    MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 101,
+    /**
+     * 111 - Protocol error, unspecified
+     */
+    PROTOCOL_ERROR_UNSPECIFIED = 111,
+}
diff --git a/radio/aidl/android/hardware/radio/network/SignalStrength.aidl b/radio/aidl/android/hardware/radio/network/SignalStrength.aidl
new file mode 100644
index 0000000..ddb4582
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/SignalStrength.aidl
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+import android.hardware.radio.network.CdmaSignalStrength;
+import android.hardware.radio.network.EvdoSignalStrength;
+import android.hardware.radio.network.GsmSignalStrength;
+import android.hardware.radio.network.LteSignalStrength;
+import android.hardware.radio.network.NrSignalStrength;
+import android.hardware.radio.network.TdscdmaSignalStrength;
+import android.hardware.radio.network.WcdmaSignalStrength;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable SignalStrength {
+    /**
+     * If GSM measurements are provided, this structure must contain valid measurements; otherwise
+     * all fields should be set to INT_MAX to mark them as invalid.
+     */
+    GsmSignalStrength gsm;
+    /**
+     * If CDMA measurements are provided, this structure must contain valid measurements; otherwise
+     * all fields should be set to INT_MAX to mark them as invalid.
+     */
+    CdmaSignalStrength cdma;
+    /**
+     * If EvDO measurements are provided, this structure must contain valid measurements; otherwise
+     * all fields should be set to INT_MAX to mark them as invalid.
+     */
+    EvdoSignalStrength evdo;
+    /**
+     * If LTE measurements are provided, this structure must contain valid measurements; otherwise
+     * all fields should be set to INT_MAX to mark them as invalid.
+     */
+    LteSignalStrength lte;
+    /**
+     * If TD-SCDMA measurements are provided, this structure must contain valid measurements;
+     * otherwise all fields should be set to INT_MAX to mark them as invalid.
+     */
+    TdscdmaSignalStrength tdscdma;
+    /**
+     * If WCDMA measurements are provided, this structure must contain valid measurements; otherwise
+     * all fields should be set to INT_MAX to mark them as invalid.
+     */
+    WcdmaSignalStrength wcdma;
+    /**
+     * If NR 5G measurements are provided, this structure must contain valid measurements; otherwise
+     * all fields should be set to INT_MAX to mark them as invalid.
+     */
+    NrSignalStrength nr;
+}
diff --git a/radio/aidl/android/hardware/radio/network/SignalThresholdInfo.aidl b/radio/aidl/android/hardware/radio/network/SignalThresholdInfo.aidl
new file mode 100644
index 0000000..2f90180
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/SignalThresholdInfo.aidl
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+import android.hardware.radio.AccessNetwork;
+
+/**
+ * Contains the threshold values of each signal measurement type.
+ */
+@VintfStability
+@JavaDerive(toString=true)
+parcelable SignalThresholdInfo {
+    /**
+     * Received Signal Strength Indication.
+     * Range: -113 dBm and -51 dBm
+     * Used RAN: GERAN, CDMA2000
+     * Reference: 3GPP TS 27.007 section 8.5.
+     */
+    const int SIGNAL_MEASUREMENT_TYPE_RSSI = 1;
+    /**
+     * Received Signal Code Power.
+     * Range: -120 dBm to -25 dBm;
+     * Used RAN: UTRAN
+     * Reference: 3GPP TS 25.123, section 9.1.1.1
+     */
+    const int SIGNAL_MEASUREMENT_TYPE_RSCP = 2;
+    /**
+     * Reference Signal Received Power.
+     * Range: -140 dBm to -44 dBm;
+     * Used RAN: EUTRAN
+     * Reference: 3GPP TS 36.133 9.1.4
+     */
+    const int SIGNAL_MEASUREMENT_TYPE_RSRP = 3;
+    /**
+     * Reference Signal Received Quality
+     * Range: -34 dB to 3 dB;
+     * Used RAN: EUTRAN
+     * Reference: 3GPP TS 36.133 v12.6.0 section 9.1.7
+     */
+    const int SIGNAL_MEASUREMENT_TYPE_RSRQ = 4;
+    /**
+     * Reference Signal Signal to Noise Ratio
+     * Range: -20 dB to 30 dB;
+     * Used RAN: EUTRAN
+     * Note: This field is optional; how to support it can be decided by the corresponding vendor.
+     * Though the response code is not enforced, vendor's implementation must ensure this interface
+     * does not crash.
+     */
+    const int SIGNAL_MEASUREMENT_TYPE_RSSNR = 5;
+    /**
+     * 5G SS reference signal received power.
+     * Range: -140 dBm to -44 dBm.
+     * Used RAN: NGRAN
+     * Reference: 3GPP TS 38.215.
+     */
+    const int SIGNAL_MEASUREMENT_TYPE_SSRSRP = 6;
+    /**
+     * 5G SS reference signal received quality.
+     * Range: -43 dB to 20 dB.
+     * Used RAN: NGRAN
+     * Reference: 3GPP TS 38.215, 3GPP TS 38.133 section 10
+     */
+    const int SIGNAL_MEASUREMENT_TYPE_SSRSRQ = 7;
+    /**
+     * 5G SS signal-to-noise and interference ratio.
+     * Range: -23 dB to 40 dB
+     * Used RAN: NGRAN
+     * Reference: 3GPP TS 38.215 section 5.1.*, 3GPP TS 38.133 section 10.1.16.1.
+     */
+    const int SIGNAL_MEASUREMENT_TYPE_SSSINR = 8;
+
+    /**
+     * Signal Measurement Type
+     * Values are SIGNAL_MEASUREMENT_TYPE_
+     */
+    int signalMeasurement;
+    /**
+     * A hysteresis time in milliseconds for current signal measurement type to prevent flapping.
+     * A value of 0 disables hysteresis.
+     */
+    int hysteresisMs;
+    /**
+     * An interval in dB for current signal measurement type defining the required magnitude change
+     * between reports. This must be smaller than the smallest threshold delta. An interval value of
+     * 0 disables hysteresis.
+     */
+    int hysteresisDb;
+    /**
+     * List of threshold values for current signal measurement type. Range and unit must reference
+     * specific SignalMeasurementType. The threshold values for which to apply criteria. A vector
+     * size of 0 disables the use of thresholds for reporting.
+     */
+    int[] thresholds;
+    /**
+     * Indicates whether the reporting criteria of the corresponding measurement is enabled
+     * (true) or disabled (false). If enabled, modem must trigger the report based on the criteria.
+     * If disabled, modem must not trigger the report based on the criteria.
+     */
+    boolean isEnabled;
+    /**
+     * The Radio Access Network for current threshold info.
+     */
+    AccessNetwork ran;
+}
diff --git a/radio/aidl/android/hardware/radio/network/SuppSvcNotification.aidl b/radio/aidl/android/hardware/radio/network/SuppSvcNotification.aidl
new file mode 100644
index 0000000..d4229e1
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/SuppSvcNotification.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable SuppSvcNotification {
+    /**
+     * Notification type
+     * false = MO intermediate result code
+     * true = MT unsolicited result code
+     */
+    boolean isMT;
+    /**
+     * Result code. See 27.007 7.17.
+     */
+    int code;
+    /**
+     * CUG index. See 27.007 7.17.
+     */
+    int index;
+    /**
+     * "type" from 27.007 7.17 (MT only).
+     */
+    int type;
+    /**
+     * "number" from 27.007 7.17. MT only, may be empty string.
+     */
+    String number;
+}
diff --git a/radio/aidl/android/hardware/radio/network/TdscdmaSignalStrength.aidl b/radio/aidl/android/hardware/radio/network/TdscdmaSignalStrength.aidl
new file mode 100644
index 0000000..ec9ca6b
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/TdscdmaSignalStrength.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable TdscdmaSignalStrength {
+    /**
+     * UTRA carrier RSSI as defined in TS 25.225 5.1.4. Valid values are (0-31, 99) as defined in
+     * TS 27.007 8.5. INT_MAX denotes that the value is invalid/unreported.
+     */
+    int signalStrength;
+    /**
+     * Transport Channel BER as defined in TS 25.225 5.2.5. Valid values are (0-7, 99) as defined in
+     * TS 27.007 8.5. INT_MAX denotes that the value is invalid/unreported.
+     */
+    int bitErrorRate;
+    /**
+     * P-CCPCH RSCP as defined in TS 25.225 5.1.1. Valid values are (0-96, 255) as defined in
+     * TS 27.007 8.69. INT_MAX denotes that the value is invalid/unreported.
+     */
+    int rscp;
+}
diff --git a/radio/aidl/android/hardware/radio/network/UsageSetting.aidl b/radio/aidl/android/hardware/radio/network/UsageSetting.aidl
new file mode 100644
index 0000000..5a714a4
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/UsageSetting.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+/**
+ * Cellular usage setting with values according to 3gpp 24.301 sec 4.3 and 3gpp 24.501 sec 4.3.
+ *
+ * <p>Also refer to "UE's usage setting" as defined in 3gpp 24.301 section 3.1 and 3gpp 23.221
+ * Annex A.
+ */
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum UsageSetting {
+    /**
+     * UE operates in voice-centric mode. Generally speaking, in this mode of operation, the UE
+     * will not remain camped on a cell or attached to a network unless that cell/network provides
+     * voice service.
+     */
+    VOICE_CENTRIC = 1,
+
+    /**
+     * UE operates in data-centric mode. Generally speaking, in this mode of operation, the UE
+     * will not reselect away from a cell/network that only provides data services.
+     */
+    DATA_CENTRIC = 2,
+}
diff --git a/radio/aidl/android/hardware/radio/network/UtranBands.aidl b/radio/aidl/android/hardware/radio/network/UtranBands.aidl
new file mode 100644
index 0000000..a0fd427
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/UtranBands.aidl
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+/**
+ * UTRAN bands up to V15.0.0
+ */
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum UtranBands {
+    BAND_1 = 1,
+    BAND_2 = 2,
+    BAND_3 = 3,
+    BAND_4 = 4,
+    BAND_5 = 5,
+    BAND_6 = 6,
+    BAND_7 = 7,
+    BAND_8 = 8,
+    BAND_9 = 9,
+    BAND_10 = 10,
+    BAND_11 = 11,
+    BAND_12 = 12,
+    BAND_13 = 13,
+    BAND_14 = 14,
+    BAND_19 = 19,
+    BAND_20 = 20,
+    BAND_21 = 21,
+    BAND_22 = 22,
+    BAND_25 = 25,
+    BAND_26 = 26,
+    /**
+     * TD-SCDMA bands. 3GPP TS 25.102, Table 5.2: Frequency bands
+     */
+    BAND_A = 101,
+    BAND_B = 102,
+    BAND_C = 103,
+    BAND_D = 104,
+    BAND_E = 105,
+    BAND_F = 106,
+}
diff --git a/radio/aidl/android/hardware/radio/network/WcdmaSignalStrength.aidl b/radio/aidl/android/hardware/radio/network/WcdmaSignalStrength.aidl
new file mode 100644
index 0000000..7595c05
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/WcdmaSignalStrength.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.network;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable WcdmaSignalStrength {
+    /**
+     * Valid values are (0-31, 99) as defined in TS 27.007 8.5; INT_MAX means unreported.
+     */
+    int signalStrength;
+    /**
+     * Bit error rate (0-7, 99) as defined in TS 27.007 8.5; INT_MAX means invalid/unreported.
+     */
+    int bitErrorRate;
+    /**
+     * CPICH RSCP as defined in TS 25.215 5.1.1. Valid values are (0-96, 255) as defined in
+     * TS 27.007 8.69. INT_MAX denotes that the value is invalid/unreported.
+     */
+    int rscp;
+    /**
+     * Ec/No value as defined in TS 25.215 5.1.5. Valid values are (0-49, 255) as defined in
+     * TS 27.007 8.69. INT_MAX denotes that the value is invalid/unreported.
+     */
+    int ecno;
+}
diff --git a/radio/aidl/android/hardware/radio/sim/AppStatus.aidl b/radio/aidl/android/hardware/radio/sim/AppStatus.aidl
new file mode 100644
index 0000000..c072f6a
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/sim/AppStatus.aidl
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.sim;
+
+import android.hardware.radio.sim.PersoSubstate;
+import android.hardware.radio.sim.PinState;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable AppStatus {
+    const int APP_STATE_UNKNOWN = 0;
+    const int APP_STATE_DETECTED = 1;
+    /**
+     * If PIN1 or UPin is required
+     */
+    const int APP_STATE_PIN = 2;
+    /**
+     * If PUK1 or Puk for Upin is required
+     */
+    const int APP_STATE_PUK = 3;
+    /**
+     * perso_substate must be looked at when app_state is assigned to this value
+     */
+    const int APP_STATE_SUBSCRIPTION_PERSO = 4;
+    const int APP_STATE_READY = 5;
+
+    const int APP_TYPE_UNKNOWN = 0;
+    const int APP_TYPE_SIM = 1;
+    const int APP_TYPE_USIM = 2;
+    const int APP_TYPE_RUIM = 3;
+    const int APP_TYPE_CSIM = 4;
+    const int APP_TYPE_ISIM = 5;
+
+    /**
+     * Values are APP_TYPE_
+     */
+    int appType;
+    /**
+     * Values are APP_STATE_
+     */
+    int appState;
+    /**
+     * Applicable only if appState == SUBSCRIPTION_PERSO
+     */
+    PersoSubstate persoSubstate;
+    /**
+     * e.g., from 0xA0, 0x00 -> 0x41, 0x30, 0x30, 0x30
+     */
+    String aidPtr;
+    String appLabelPtr;
+    /**
+     * Applicable to USIM, CSIM and ISIM
+     */
+    boolean pin1Replaced;
+    PinState pin1;
+    PinState pin2;
+}
diff --git a/radio/aidl/android/hardware/radio/sim/CardPowerState.aidl b/radio/aidl/android/hardware/radio/sim/CardPowerState.aidl
new file mode 100644
index 0000000..f8b5922
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/sim/CardPowerState.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.sim;
+
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum CardPowerState {
+    POWER_DOWN,
+    POWER_UP,
+    POWER_UP_PASS_THROUGH,
+}
diff --git a/radio/aidl/android/hardware/radio/sim/CardStatus.aidl b/radio/aidl/android/hardware/radio/sim/CardStatus.aidl
new file mode 100644
index 0000000..a14cf7d
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/sim/CardStatus.aidl
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.sim;
+
+import android.hardware.radio.config.SlotPortMapping;
+import android.hardware.radio.sim.AppStatus;
+import android.hardware.radio.sim.PinState;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable CardStatus {
+    /*
+     * Card is physically absent from device. (Some old modems use STATE_ABSENT when the SIM
+     * is powered off. This is no longer correct, however the platform will still support this
+     * legacy behavior.)
+     */
+    const int STATE_ABSENT = 0;
+    /*
+     * Card is inserted in the device
+     */
+    const int STATE_PRESENT = 1;
+    const int STATE_ERROR = 2;
+    /*
+     * Card is present but not usable due to carrier restrictions
+     */
+    const int STATE_RESTRICTED = 3;
+
+    /**
+     * Values are STATE_
+     */
+    int cardState;
+    /**
+     * Applicable to USIM and CSIM
+     */
+    PinState universalPinState;
+    /**
+     * Value < RadioConst:CARD_MAX_APPS, -1 if none
+     */
+    int gsmUmtsSubscriptionAppIndex;
+    /**
+     * Value < RadioConst:CARD_MAX_APPS, -1 if none
+     */
+    int cdmaSubscriptionAppIndex;
+    /**
+     * Value < RadioConst:CARD_MAX_APPS, -1 if none
+     */
+    int imsSubscriptionAppIndex;
+    /**
+     * size <= RadioConst::CARD_MAX_APPS
+     */
+    AppStatus[] applications;
+    /**
+     * An Answer To Reset (ATR) is a message output by a Smart Card conforming to ISO/IEC 7816
+     * standards, following electrical reset of the card's chip. The ATR conveys information about
+     * the communication parameters proposed by the card, and the card's nature and state.
+     *
+     * This data is applicable only when cardState is STATE_PRESENT.
+     */
+    String atr;
+    /**
+     * Integrated Circuit Card IDentifier (ICCID) is Unique Identifier of the SIM CARD. File is
+     * located in the SIM card at EFiccid (0x2FE2) as per ETSI 102.221. The ICCID is defined by
+     * the ITU-T recommendation E.118 ISO/IEC 7816.
+     *
+     * This data is applicable only when cardState is STATE_PRESENT.
+     */
+    String iccid;
+    /**
+     * The EID is the eUICC identifier. The EID shall be stored within the ECASD and can be
+     * retrieved by the Device at any time using the standard GlobalPlatform GET DATA command.
+     *
+     * This data is mandatory and applicable only when cardState is STATE_PRESENT and SIM card
+     * supports eUICC.
+     */
+    String eid;
+    /* SlotPortMapping:
+     * SlotPortMapping consists of physical slot id and port id.
+     * Physical slot is the actual physical slot.
+     * PortId is the id (enumerated value) for the associated port available on the SIM.
+     */
+    SlotPortMapping slotMap;
+}
diff --git a/radio/aidl/android/hardware/radio/sim/Carrier.aidl b/radio/aidl/android/hardware/radio/sim/Carrier.aidl
new file mode 100644
index 0000000..d25214f
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/sim/Carrier.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.sim;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable Carrier {
+    /**
+     * Apply to all carrier with the same mcc/mnc
+     */
+    const int MATCH_TYPE_ALL = 0;
+    /**
+     * Use SPN and mcc/mnc to identify the carrier
+     */
+    const int MATCH_TYPE_SPN = 1;
+    /**
+     * Use IMSI prefix and mcc/mnc to identify the carrier
+     */
+    const int MATCH_TYPE_IMSI_PREFIX = 2;
+    /**
+     * Use GID1 and mcc/mnc to identify the carrier
+     */
+    const int MATCH_TYPE_GID1 = 3;
+    /**
+     * Use GID2 and mcc/mnc to identify the carrier
+     */
+    const int MATCH_TYPE_GID2 = 4;
+
+    String mcc;
+    String mnc;
+    /**
+     * Specify match type for the carrier. If it’s MATCH_TYPE_ALL, matchData is empty string;
+     * otherwise, matchData is the value for the match type.
+     * Values are MATCH_TYPE_
+     */
+    int matchType;
+    String matchData;
+}
diff --git a/radio/aidl/android/hardware/radio/sim/CarrierRestrictions.aidl b/radio/aidl/android/hardware/radio/sim/CarrierRestrictions.aidl
new file mode 100644
index 0000000..3dce907
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/sim/CarrierRestrictions.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.sim;
+
+import android.hardware.radio.sim.Carrier;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable CarrierRestrictions {
+    /**
+     * Allowed carriers
+     */
+    Carrier[] allowedCarriers;
+    /**
+     * Explicitly excluded carriers which match allowed_carriers. Eg. allowedCarriers match mcc/mnc,
+     * excludedCarriers has same mcc/mnc and gid1 is ABCD. It means except the carrier whose gid1
+     * is ABCD, all carriers with the same mcc/mnc are allowed.
+     */
+    Carrier[] excludedCarriers;
+    /**
+     * True means that only carriers included in the allowed list and not in the excluded list
+     * are permitted. Eg. allowedCarriers match mcc/mnc, excludedCarriers has same mcc/mnc and
+     * gid1 is ABCD. It means except the carrier whose gid1 is ABCD, all carriers with the
+     * same mcc/mnc are allowed.
+     * False means that all carriers are allowed except those included in the excluded list
+     * and not in the allowed list.
+     */
+    boolean allowedCarriersPrioritized;
+}
diff --git a/radio/aidl/android/hardware/radio/sim/CdmaSubscriptionSource.aidl b/radio/aidl/android/hardware/radio/sim/CdmaSubscriptionSource.aidl
new file mode 100644
index 0000000..6aa6926
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/sim/CdmaSubscriptionSource.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.sim;
+
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum CdmaSubscriptionSource {
+    RUIM_SIM,
+    NV,
+}
diff --git a/radio/aidl/android/hardware/radio/sim/IRadioSim.aidl b/radio/aidl/android/hardware/radio/sim/IRadioSim.aidl
new file mode 100644
index 0000000..7923b14
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/sim/IRadioSim.aidl
@@ -0,0 +1,497 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.sim;
+
+import android.hardware.radio.sim.CardPowerState;
+import android.hardware.radio.sim.CarrierRestrictions;
+import android.hardware.radio.sim.CdmaSubscriptionSource;
+import android.hardware.radio.sim.IRadioSimIndication;
+import android.hardware.radio.sim.IRadioSimResponse;
+import android.hardware.radio.sim.IccIo;
+import android.hardware.radio.sim.ImsiEncryptionInfo;
+import android.hardware.radio.sim.PersoSubstate;
+import android.hardware.radio.sim.PhonebookRecordInfo;
+import android.hardware.radio.sim.SelectUiccSub;
+import android.hardware.radio.sim.SimApdu;
+import android.hardware.radio.sim.SimLockMultiSimPolicy;
+
+/**
+ * This interface is used by telephony and telecom to talk to cellular radio for SIM APIs.
+ * All the functions have minimum one parameter:
+ * serial: which corresponds to serial no. of request. Serial numbers must only be memorized for the
+ * duration of a method call. If clients provide colliding serials (including passing the same
+ * serial to different methods), multiple responses (one for each method call) must still be served.
+ * setResponseFunctions must work with IRadioSimResponse and IRadioSimIndication.
+ */
+@VintfStability
+oneway interface IRadioSim {
+    /**
+     * Whether uiccApplications are enabled or disabled.
+     * By default uiccApplications must be enabled, unless enableUiccApplications() with enable
+     * being false is called.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioSimResponse.areUiccApplicationsEnabledResponse()
+     */
+    void areUiccApplicationsEnabled(in int serial);
+
+    /**
+     * Supplies old ICC PIN2 and new PIN2.
+     *
+     * @param serial Serial number of request.
+     * @param oldPin2 Old pin2 value
+     * @param newPin2 New pin2 value
+     * @param aid AID value, See ETSI 102.221 8.1 and 101.220 4, empty string if no value.
+     *
+     * Response function is IRadioSimResponse.changeIccPin2ForAppResponse()
+     */
+    void changeIccPin2ForApp(in int serial, in String oldPin2, in String newPin2, in String aid);
+
+    /**
+     * Supplies old ICC PIN and new PIN.
+     *
+     * @param serial Serial number of request.
+     * @param oldPin Old pin value
+     * @param newPin New pin value
+     * @param aid AID value, See ETSI 102.221 8.1 and 101.220 4, empty string if no value.
+     *
+     * Response function is IRadioSimResponse.changeIccPinForAppResponse()
+     */
+    void changeIccPinForApp(in int serial, in String oldPin, in String newPin, in String aid);
+
+    /**
+     * Enable or disable UiccApplications on the SIM. If disabled:
+     *  - Modem will not register on any network.
+     *  - SIM must be PRESENT, and the IccId of the SIM must still be accessible.
+     *  - The corresponding modem stack is still functional, e.g. able to make emergency calls or
+     *    do network scan.
+     * By default if this API is not called, the uiccApplications must be enabled automatically.
+     * It must work for both single SIM and DSDS cases for UX consistency.
+     * The preference is per SIM, and must be remembered over power cycle, modem reboot, or SIM
+     * insertion / unplug.
+     *
+     * @param serial Serial number of request.
+     * @param enable true if to enable uiccApplications, false to disable.
+     *
+     * Response function is IRadioSimResponse.enableUiccApplicationsResponse()
+     */
+    void enableUiccApplications(in int serial, in boolean enable);
+
+    /**
+     * Get carrier restrictions.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioSimResponse.getAllowedCarriersResponse()
+     */
+    void getAllowedCarriers(in int serial);
+
+    /**
+     * Request the device MDN / H_SID / H_NID. The request is only allowed when CDMA subscription
+     * is available. When CDMA subscription is changed, application layer must re-issue the request
+     * to update the subscription information.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioSimResponse.getCdmaSubscriptionResponse()
+     */
+    void getCdmaSubscription(in int serial);
+
+    /**
+     * Request to query the location where the CDMA subscription shall be retrieved.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioSimResponse.getCdmaSubscriptionSourceResponse()
+     */
+    void getCdmaSubscriptionSource(in int serial);
+
+    /**
+     * Query the status of a facility lock state
+     *
+     * @param serial Serial number of request.
+     * @param facility is the facility string code from TS 27.007 7.4
+     *        (eg "AO" for BAOC, "SC" for SIM lock)
+     * @param password is the password, or "" if not required
+     * @param serviceClass is the TS 27.007 service class bit vector of services to query
+     * @param appId is AID value, See ETSI 102.221 8.1 and 101.220 4, empty string if no value.
+     *        This is only applicable in the case of Fixed Dialing Numbers (FDN) requests.
+     *
+     * Response function is IRadioSimResponse.getFacilityLockForAppResponse()
+     */
+    void getFacilityLockForApp(in int serial, in String facility, in String password,
+            in int serviceClass, in String appId);
+
+    /**
+     * Requests status of the ICC card
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioSimResponse.getIccCardStatusResponse()
+     */
+    void getIccCardStatus(in int serial);
+
+    /**
+     * Get the SIM IMSI. Only valid when radio state is "RADIO_STATE_ON"
+     *
+     * @param serial Serial number of request.
+     * @param aid AID value, See ETSI 102.221 8.1 and 101.220 4, empty string if no value.
+     *
+     * Response function is IRadioSimResponse.getImsiForAppResponse()
+     */
+    void getImsiForApp(in int serial, in String aid);
+
+    /**
+     * Get the phonebook capacity.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioSimResponse.getSimPhonebookCapacityResponse()
+     */
+    void getSimPhonebookCapacity(in int serial);
+
+    /**
+     * Get the local and global phonebook records from the SIM card.
+     * This should be called again after a simPhonebookChanged notification is received.
+     * The phonebook records are received via IRadioSimIndication.simPhonebookRecordsReceived()
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioSimResponse.getSimPhonebookRecordsResponse()
+     */
+    void getSimPhonebookRecords(in int serial);
+
+    /**
+     * Close a previously opened logical channel. This command reflects TS 27.007
+     * "close logical channel" operation (+CCHC).
+     *
+     * @param serial Serial number of request.
+     * @param channelId session id of the logical channel (+CCHC).
+     *
+     * Response function is IRadioSimResponse.iccCloseLogicalChannelResponse()
+     */
+    void iccCloseLogicalChannel(in int serial, in int channelId);
+
+    /**
+     * Request ICC I/O operation. This is similar to the TS 27.007 "restricted SIM" operation where
+     * it assumes all of the EF selection must be done by the callee. Arguments and responses that
+     * are unused for certain values of "command" must be ignored or set to empty string.
+     * Note that IccIo has a "PIN2" field which may be empty string, or may specify a PIN2 for
+     * operations that require a PIN2 (eg updating FDN records).
+     *
+     * @param serial Serial number of request.
+     * @param iccIo IccIo
+     *
+     * Response function is IRadioSimResponse.iccIoForAppResponse()
+     */
+    void iccIoForApp(in int serial, in IccIo iccIo);
+
+    /**
+     * Open a new logical channel and select the given application. This command
+     * reflects TS 27.007 "open logical channel" operation (+CCHO).
+     *
+     * For MEP-A(Multiple enabled profile), only dedicated port 0 is ISDR selectable.
+     * e.g., Port0 - for ISDR access and Port1/Port2 - the currently active ports/subscriptions.
+     * Port 0 should be transparent to AP and iccLogicalChannel API should remain the same.
+     * Even if the ISDR request comes over port1 or port2, Modem would just internally convert the
+     * portID to port0 and add the real port index as the payload of MANAGE_CHANNEL command.
+     *
+     * @param serial Serial number of request.
+     * @param aid AID value, See ETSI 102.221 and 101.220.
+     * @param p2 P2 value, described in ISO 7816-4. Ignore if equal to RadioConst:P2_CONSTANT_NO_P2
+     *
+     * Response function is IRadioSimResponse.iccOpenLogicalChannelResponse()
+     */
+    void iccOpenLogicalChannel(in int serial, in String aid, in int p2);
+
+    /**
+     * Request APDU exchange on the basic channel. This command reflects TS 27.007
+     * "generic SIM access" operation (+CSIM). The modem must ensure proper function of GSM/CDMA,
+     * and filter commands appropriately. It must filter channel management and SELECT by DF
+     * name commands. "sessionid" field must be ignored.
+     *
+     * @param serial Serial number of request.
+     * @param message SimApdu to be sent
+     *
+     * Response function is IRadioSimResponse.iccTransmitApduBasicChannelResponse()
+     */
+    void iccTransmitApduBasicChannel(in int serial, in SimApdu message);
+
+    /**
+     * Exchange APDUs with a UICC over a previously opened logical channel. This command reflects
+     * TS 27.007 "generic logical channel access" operation (+CGLA). The modem must filter channel
+     * management and SELECT by DF name commands.
+     *
+     * @param serial Serial number of request.
+     * @param message SimApdu to be sent
+     *
+     * Response function is IRadioSimResponse.iccTransmitApduLogicalChannelResponse()
+     */
+    void iccTransmitApduLogicalChannel(in int serial, in SimApdu message);
+
+    /**
+     * Indicates that the StkService is running and is ready to receive unsolicited stk commands.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioSimResponse.reportStkServiceIsRunningResponse()
+     */
+    void reportStkServiceIsRunning(in int serial);
+
+    /**
+     * Returns the response of SIM Authentication through Radio challenge request.
+     *
+     * @param serial Serial number of request.
+     * @param authContext P2 value of authentication command, see P2 parameter in
+     *        3GPP TS 31.102 7.1.2
+     * @param authData the challenge string in Base64 format, see 3GPP TS 31.102 7.1.2
+     * @param aid AID value, See ETSI 102.221 8.1 and 101.220 4, empty string if no value
+     *
+     * Response function is IRadioSimResponse.requestIccSimAuthenticationResponse()
+     */
+    void requestIccSimAuthentication(
+            in int serial, in int authContext, in String authData, in String aid);
+
+    /**
+     * When response type received from a radio indication or radio response is
+     * RadioIndicationType:UNSOLICITED_ACK_EXP or RadioResponseType:SOLICITED_ACK_EXP respectively,
+     * acknowledge the receipt of those messages by sending responseAcknowledgement().
+     */
+    void responseAcknowledgement();
+
+    /**
+     * Requests to send a SAT/USAT envelope command to SIM.
+     * The SAT/USAT envelope command refers to 3GPP TS 11.14 and 3GPP TS 31.111
+     *
+     * @param serial Serial number of request.
+     * @param contents SAT/USAT command in hexadecimal format string starting with command tag
+     *
+     * Response function is IRadioSimResponse.sendEnvelopeResponse()
+     */
+    void sendEnvelope(in int serial, in String contents);
+
+    /**
+     * Requests to send a SAT/USAT envelope command to SIM. The SAT/USAT envelope command refers to
+     * 3GPP TS 11.14 and 3GPP TS 31.111. This request has one difference from sendEnvelope():
+     * The SW1 and SW2 status bytes from the UICC response are returned along with the response
+     * data, using the same structure as iccIOForApp(). The implementation must perform normal
+     * processing of a '91XX' response in SW1/SW2 to retrieve the pending proactive command and
+     * send it as an unsolicited response, as sendEnvelope() does.
+     *
+     * @param serial Serial number of request.
+     * @param contents SAT/USAT command in hexadecimal format starting with command tag
+     *
+     * Response function is IRadioSimResponse.sendEnvelopeWithStatusResponse()
+     */
+    void sendEnvelopeWithStatus(in int serial, in String contents);
+
+    /**
+     * Requests to send a terminal response to SIM for a received proactive command
+     *
+     * @param serial Serial number of request.
+     * @param contents SAT/USAT response in hexadecimal format string starting with
+     *        first byte of response data
+     *
+     * Response function is IRadioSimResponse.sendTerminalResponseResponseToSim()
+     */
+    void sendTerminalResponseToSim(in int serial, in String contents);
+
+    /**
+     * Set carrier restrictions. Expected modem behavior:
+     *  If never receives this command:
+     *  - Must allow all carriers
+     *  Receives this command:
+     *  - Only allow carriers specified in carriers. The restriction persists across power cycles
+     *    and FDR. If a present SIM is allowed, modem must not reload the SIM. If a present SIM is
+     *    *not* allowed, modem must detach from the registered network and only keep emergency
+     *    service, and notify Android SIM refresh reset with new SIM state being
+     *    CardState:RESTRICTED. Emergency service must be enabled.
+     *
+     * @param serial Serial number of request.
+     * @param carriers CarrierRestrictions consisting allowed and excluded carriers
+     * @param multiSimPolicy Policy to be used for devices with multiple SIMs.
+     *
+     * Response function is IRadioSimResponse.setAllowedCarriersResponse()
+     */
+    void setAllowedCarriers(in int serial, in CarrierRestrictions carriers,
+            in SimLockMultiSimPolicy multiSimPolicy);
+
+    /**
+     * Provide Carrier specific information to the modem that must be used to encrypt the IMSI and
+     * IMPI. Sent by the framework during boot, carrier switch and everytime the framework receives
+     * a new certificate.
+     *
+     * @param serial Serial number of request.
+     * @param imsiEncryptionInfo ImsiEncryptionInfo
+     *
+     * Response function is IRadioSimResponse.setCarrierInfoForImsiEncryptionResponse()
+     */
+    void setCarrierInfoForImsiEncryption(in int serial, in ImsiEncryptionInfo imsiEncryptionInfo);
+
+    /**
+     * Request to set the location where the CDMA subscription shall be retrieved
+     *
+     * @param serial Serial number of request.
+     * @param cdmaSub CdmaSubscriptionSource
+     *
+     * Response function is IRadioSimResponse.setCdmaSubscriptionSourceResponse()
+     */
+    void setCdmaSubscriptionSource(in int serial, in CdmaSubscriptionSource cdmaSub);
+
+    /**
+     * Enable/disable one facility lock
+     *
+     * @param serial Serial number of request.
+     * @param facility is the facility string code from TS 27.007 7.4 (eg "AO" for BAOC)
+     * @param lockState false for "unlock" and true for "lock"
+     * @param password is the password
+     * @param serviceClass is string representation of decimal TS 27.007 service class bit vector.
+     *        Eg, the string "1" means "set this facility for voice services"
+     * @param appId is AID value, See ETSI 102.221 8.1 and 101.220 4, empty string if no value.
+     *        This is only applicable in the case of Fixed Dialing Numbers (FDN) requests.
+     *
+     * Response function is IRadioSimResponse.setFacilityLockForAppResponse()
+     */
+    void setFacilityLockForApp(in int serial, in String facility, in boolean lockState,
+            in String password, in int serviceClass, in String appId);
+
+    /**
+     * Set response functions for SIM radio requests and indications.
+     *
+     * @param radioSimResponse Object containing response functions
+     * @param radioSimIndication Object containing radio indications
+     */
+    void setResponseFunctions(
+            in IRadioSimResponse radioSimResponse, in IRadioSimIndication radioSimIndication);
+
+    /**
+     * Set SIM card power state. Request is used to power off or power on the card. It should not
+     * generate a CardState.CARDSTATE_ABSENT indication, since the SIM is still physically inserted.
+     * When SIM card is in POWER_UP_PASS_THROUGH, the modem does not send any command to it (for
+     * example SELECT of MF, or TERMINAL CAPABILITY), and the SIM card is controlled completely by
+     * Telephony sending APDUs directly. The SIM card state must be RIL_CARDSTATE_PRESENT and the
+     * number of card apps will be 0. No new error code is generated. Emergency calls are supported
+     * in the same way as if the SIM card is absent. Pass-through mode is valid only for the
+     * specific card session where it is activated, and normal behavior occurs at the next SIM
+     * initialization, unless POWER_UP_PASS_THROUGH is requested again.
+     * The device is required to power down the SIM card before it can switch the mode between
+     * POWER_UP and POWER_UP_PASS_THROUGH. At device power up, the SIM interface is powered up
+     * automatically. Each subsequent request to this method is processed only after the completion
+     * of the previous one.
+     * When the SIM is in POWER_DOWN, the modem should send an empty vector of AppStatus in
+     * CardStatus.applications. If a SIM in the POWER_DOWN state is removed and a new SIM is
+     * inserted, the new SIM should be in POWER_UP mode by default. If the device is turned off or
+     * restarted while the SIM is in POWER_DOWN, then the SIM should turn on normally in POWER_UP
+     * mode when the device turns back on.
+     *
+     * @param serial Serial number of request
+     * @param powerUp POWER_DOWN if powering down the SIM card
+     *                POWER_UP if powering up the SIM card
+     *                POWER_UP_PASS_THROUGH if powering up the SIM card in pass through mode
+     *
+     * Response function is IRadioSimResponse.setSimCardPowerResponse()
+     */
+    void setSimCardPower(in int serial, in CardPowerState powerUp);
+
+    /**
+     * Selection/de-selection of a subscription from a SIM card
+     *
+     * @param serial Serial number of request.
+     * @param uiccSub SelectUiccSub
+     *
+     * Response function is IRadioSimResponse.setUiccSubscriptionResponse()
+     */
+    void setUiccSubscription(in int serial, in SelectUiccSub uiccSub);
+
+    /**
+     * Supplies ICC PIN2. Only called following operation where SIM_PIN2 was returned as a failure
+     * from a previous operation.
+     *
+     * @param serial Serial number of request.
+     * @param pin2 PIN2 value
+     * @param aid AID value, See ETSI 102.221 8.1 and 101.220 4, empty string if no value.
+     *
+     * Response function is IRadioSimResponse.supplyIccPin2ForAppResponse()
+     */
+    void supplyIccPin2ForApp(in int serial, in String pin2, in String aid);
+
+    /**
+     * Supplies ICC PIN. Only called if CardStatus has AppState.PIN state
+     *
+     * @param serial Serial number of request.
+     * @param pin PIN value
+     * @param aid AID value, See ETSI 102.221 8.1 and 101.220 4, empty string if no value.
+     *
+     * Response function is IRadioSimResponse.supplyIccPinForAppResponse()
+     */
+    void supplyIccPinForApp(in int serial, in String pin, in String aid);
+
+    /**
+     * Supplies ICC PUK2 and new PIN2.
+     *
+     * @param serial Serial number of request.
+     * @param puk2 PUK2 value
+     * @param pin2 New PIN2 value
+     * @param aid AID value, See ETSI 102.221 8.1 and 101.220 4, empty string if no value.
+     *
+     * Response function is IRadioSimResponse.supplyIccPuk2ForAppResponse()
+     */
+    void supplyIccPuk2ForApp(in int serial, in String puk2, in String pin2, in String aid);
+
+    /**
+     * Supplies ICC PUK and new PIN.
+     *
+     * @param serial Serial number of request.
+     * @param puk PUK value
+     * @param pin New PIN value
+     * @param aid AID value, See ETSI 102.221 8.1 and 101.220 4, empty string if no value.
+     *
+     * Response function is IRadioSimResponse.supplyIccPukForAppResponse()
+     */
+    void supplyIccPukForApp(in int serial, in String puk, in String pin, in String aid);
+
+    /**
+     * Request that deactivates one category of device personalization. Device personalization
+     * generally binds the device so it can only be used on one carrier or even one carrier subnet
+     * (See TS 22.022). When the user has gained the rights to unbind the device (at the end of a
+     * contract period or other event), the controlKey will be delivered to either the user for
+     * manual entry or to a carrier app on the device for automatic entry.
+     *
+     * @param serial Serial number of request.
+     * @param persoType SIM personalization type.
+     * @param controlKey the unlock code for removing persoType personalization from this device
+     *
+     * Response function is IRadioSimResponse.supplySimDepersonalizationResponse()
+     */
+    void supplySimDepersonalization(
+            in int serial, in PersoSubstate persoType, in String controlKey);
+
+    /**
+     * Insert, delete or update a phonebook record on the SIM card. If the index of recordInfo is 0,
+     * the phonebook record will be added to global or local phonebook, and global phonebook has
+     * higher priority than local phonebook. If the fields in the recordInfo are all empty except
+     * for the index, the phonebook record specified by the index will be deleted. The indication
+     * simPhonebookChanged will be called after every successful call of updateSimPhonebookRecords.
+     *
+     * @param serial Serial number of request.
+     * @param recordInfo Details of the record to insert, delete or update.
+     *
+     * Response function is IRadioSimResponse.updateSimPhonebookRecordsResponse()
+     */
+    void updateSimPhonebookRecords(in int serial, in PhonebookRecordInfo recordInfo);
+}
diff --git a/radio/aidl/android/hardware/radio/sim/IRadioSimIndication.aidl b/radio/aidl/android/hardware/radio/sim/IRadioSimIndication.aidl
new file mode 100644
index 0000000..a139040
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/sim/IRadioSimIndication.aidl
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.sim;
+
+import android.hardware.radio.RadioIndicationType;
+import android.hardware.radio.sim.CdmaSubscriptionSource;
+import android.hardware.radio.sim.PbReceivedStatus;
+import android.hardware.radio.sim.PhonebookRecordInfo;
+import android.hardware.radio.sim.SimRefreshResult;
+
+/**
+ * Interface declaring unsolicited radio indications for SIM APIs.
+ */
+@VintfStability
+oneway interface IRadioSimIndication {
+    /**
+     * Indicates that the modem requires the Carrier info for IMSI/IMPI encryption. This might
+     * happen when the modem restarts or for some reason it's cache has been invalidated.
+     *
+     * @param type Type of radio indication
+     */
+    void carrierInfoForImsiEncryption(in RadioIndicationType info);
+
+    /**
+     * Indicates when CDMA subscription source changed.
+     *
+     * @param type Type of radio indication
+     * @param cdmaSource New CdmaSubscriptionSource
+     */
+    void cdmaSubscriptionSourceChanged(
+            in RadioIndicationType type, in CdmaSubscriptionSource cdmaSource);
+
+    /**
+     * Indicates whether SIM phonebook is changed. This indication is sent whenever the SIM
+     * phonebook is changed, including SIM is inserted or removed and updated by
+     * IRadioSim.updateSimPhonebookRecords.
+     *
+     * @param type Type of radio indication
+     */
+    void simPhonebookChanged(in RadioIndicationType type);
+
+    /**
+     * Indicates the content of all the used records in the SIM phonebook. This indication is
+     * associated with the API getSimPhonebookRecords and might be received more than once that is
+     * replying on the record count.
+     *
+     * @param type Type of radio indication
+     * @param status Status of PbReceivedStatus
+     * @param records Vector of PhonebookRecordInfo
+     */
+    void simPhonebookRecordsReceived(in RadioIndicationType type, in PbReceivedStatus status,
+            in PhonebookRecordInfo[] records);
+
+    /**
+     * Indicates that file(s) on the SIM have been updated, or the SIM has been reinitialized.
+     * If the SIM state changes as a result of the SIM refresh (eg, SIM_READY ->
+     * SIM_LOCKED_OR_ABSENT), simStatusChanged() must be sent.
+     *
+     * @param type Type of radio indication
+     * @param refreshResult Result of sim refresh
+     */
+    void simRefresh(in RadioIndicationType type, in SimRefreshResult refreshResult);
+
+    /**
+     * Indicates that SIM state changes. Callee must invoke getIccCardStatus().
+     *
+     * @param type Type of radio indication
+     */
+    void simStatusChanged(in RadioIndicationType type);
+
+    /**
+     * Indicates when SIM notifies applcations some event happens.
+     *
+     * @param type Type of radio indication
+     * @param cmd SAT/USAT commands or responses sent by ME to SIM or commands handled by ME,
+     *        represented as byte array starting with first byte of response data for command tag.
+     *        Refer to TS 102.223 section 9.4 for command types
+     */
+    void stkEventNotify(in RadioIndicationType type, in String cmd);
+
+    /**
+     * Indicates when SIM issue a STK proactive command to applications.
+     *
+     * @param type Type of radio indication
+     * @param cmd SAT/USAT proactive represented as byte array starting with command tag.
+     *        Refer to TS 102.223 section 9.4 for command types
+     */
+    void stkProactiveCommand(in RadioIndicationType type, in String cmd);
+
+    /**
+     * Indicates when STK session is terminated by SIM.
+     *
+     * @param type Type of radio indication
+     */
+    void stkSessionEnd(in RadioIndicationType type);
+
+    /**
+     * Indicated when there is a change in subscription status.
+     * This event must be sent in the following scenarios
+     * - subscription readiness at modem, which was selected by telephony layer
+     * - when subscription is deactivated by modem due to UICC card removal
+     * - when network invalidates the subscription i.e. attach reject due to authentication reject
+     *
+     * @param type Type of radio indication
+     * @param activate false for subscription deactivated, true for subscription activated
+     */
+    void subscriptionStatusChanged(in RadioIndicationType type, in boolean activate);
+
+    /**
+     * Report change of whether uiccApplications are enabled, or disabled.
+     *
+     * @param type Type of radio indication
+     * @param enabled whether uiccApplications are enabled or disabled
+     */
+    void uiccApplicationsEnablementChanged(in RadioIndicationType type, in boolean enabled);
+}
diff --git a/radio/aidl/android/hardware/radio/sim/IRadioSimResponse.aidl b/radio/aidl/android/hardware/radio/sim/IRadioSimResponse.aidl
new file mode 100644
index 0000000..750a29a
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/sim/IRadioSimResponse.aidl
@@ -0,0 +1,631 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.sim;
+
+import android.hardware.radio.RadioResponseInfo;
+import android.hardware.radio.sim.CardStatus;
+import android.hardware.radio.sim.CarrierRestrictions;
+import android.hardware.radio.sim.CdmaSubscriptionSource;
+import android.hardware.radio.sim.IccIoResult;
+import android.hardware.radio.sim.PersoSubstate;
+import android.hardware.radio.sim.PhonebookCapacity;
+import android.hardware.radio.sim.SimLockMultiSimPolicy;
+
+/**
+ * Interface declaring response functions to solicited radio requests for SIM APIs.
+ */
+@VintfStability
+oneway interface IRadioSimResponse {
+    /**
+     * Acknowledge the receipt of radio request sent to the vendor. This must be sent only for
+     * radio request which take long time to respond. For more details, refer
+     * https://source.android.com/devices/tech/connect/ril.html
+     *
+     * @param serial Serial no. of the request whose acknowledgement is sent.
+     */
+    void acknowledgeRequest(in int serial);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param enabled whether Uicc applications are enabled.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:SIM_ABSENT
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     */
+    void areUiccApplicationsEnabledResponse(in RadioResponseInfo info, in boolean enabled);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param remainingRetries Number of retries remaining, must be equal to -1 if unknown.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE (radio resetting)
+     *   RadioError:PASSWORD_INCORRECT (old PIN2 is invalid)
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_SIM_STATE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:SIM_PUK2
+     */
+    void changeIccPin2ForAppResponse(in RadioResponseInfo info, in int remainingRetries);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param remainingRetries Number of retries remaining, must be equal to -1 if unknown.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE (radio resetting)
+     *   RadioError:PASSWORD_INCORRECT
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_SIM_STATE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void changeIccPinForAppResponse(in RadioResponseInfo info, in int remainingRetries);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:SIM_ABSENT
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:BUSY
+     */
+    void enableUiccApplicationsResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param carriers Carrier restriction information.
+     * @param multiSimPolicy Policy used for devices with multiple SIM cards.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void getAllowedCarriersResponse(in RadioResponseInfo info, in CarrierRestrictions carriers,
+            in SimLockMultiSimPolicy multiSimPolicy);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param mdn MDN if CDMA subscription is available
+     * @param hSid is a comma separated list of H_SID (Home SID) if CDMA subscription is available,
+     *        in decimal format
+     * @param hNid is a comma separated list of H_NID (Home NID) if CDMA subscription is available,
+     *        in decimal format
+     * @param min MIN (10 digits, MIN2+MIN1) if CDMA subscription is available
+     * @param prl PRL version if CDMA subscription is available
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:SUBSCRIPTION_NOT_AVAILABLE
+     *   RadioError:NO_MEMORY
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:MODEM_ERR
+     *   RadioError:NOT_PROVISIONED
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:SIM_ABSENT
+     */
+    void getCdmaSubscriptionResponse(in RadioResponseInfo info, in String mdn, in String hSid,
+            in String hNid, in String min, in String prl);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param source CDMA subscription source
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:SUBSCRIPTION_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:SIM_ABSENT
+     */
+    void getCdmaSubscriptionSourceResponse(
+            in RadioResponseInfo info, in CdmaSubscriptionSource source);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param response 0 is the TS 27.007 service class bit vector of services for which the
+     *        specified barring facility is active. "0" means "disabled for all"
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:SS_MODIFIED_TO_DIAL
+     *   RadioError:SS_MODIFIED_TO_USSD
+     *   RadioError:SS_MODIFIED_TO_SS
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:NO_MEMORY
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:FDN_CHECK_FAILURE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void getFacilityLockForAppResponse(in RadioResponseInfo info, in int response);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param cardStatus ICC card status as defined by CardStatus
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_RESOURCES
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void getIccCardStatusResponse(in RadioResponseInfo info, in CardStatus cardStatus);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param imsi String containing the IMSI
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE (radio resetting)
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:INVALID_SIM_STATE
+     *   RadioError:SIM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void getImsiForAppResponse(in RadioResponseInfo info, in String imsi);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param capacity Response capacity enum indicating response processing status
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_SIM_STATE
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     * REQUEST_NOT_SUPPORTED may only be returned on devices that don't support this API,
+     * indicated by the HAL capability CAPABILITY_SIM_PHONEBOOK_IN_MODEM.
+     */
+    void getSimPhonebookCapacityResponse(in RadioResponseInfo info, in PhonebookCapacity capacity);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_SIM_STATE
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     * REQUEST_NOT_SUPPORTED may only be returned on devices that don't support this API,
+     * indicated by the HAL capability CAPABILITY_SIM_PHONEBOOK_IN_MODEM.
+     */
+    void getSimPhonebookRecordsResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void iccCloseLogicalChannelResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param iccIo ICC IO operation response
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:SIM_PIN2
+     *   RadioError:SIM_PUK2
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:INVALID_SIM_STATE
+     *   RadioError:SIM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void iccIoForAppResponse(in RadioResponseInfo info, in IccIoResult iccIo);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param channelId session id of the logical channel.
+     * @param selectResponse Contains the select response for the open channel command with one
+     *        byte per integer
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:MISSING_RESOURCE
+     *   RadioError:NO_SUCH_ELEMENT
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:SIM_ERR
+     *   RadioError:INVALID_SIM_STATE
+     *   RadioError:MISSING_RESOURCE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void iccOpenLogicalChannelResponse(
+            in RadioResponseInfo info, in int channelId, in byte[] selectResponse);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param result IccIoResult
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void iccTransmitApduBasicChannelResponse(in RadioResponseInfo info, in IccIoResult result);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param result IccIoResult
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void iccTransmitApduLogicalChannelResponse(in RadioResponseInfo info, in IccIoResult result);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void reportStkServiceIsRunningResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param result IccIoResult
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:SIM_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void requestIccSimAuthenticationResponse(in RadioResponseInfo info, in IccIoResult result);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param commandResponse SAT/USAT response in hexadecimal format string starting with first
+     *        byte of response
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:SIM_BUSY
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:MODEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:SIM_ABSENT
+     */
+    void sendEnvelopeResponse(in RadioResponseInfo info, in String commandResponse);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param iccIo IccIoResult corresponding to ICC IO response
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:SIM_BUSY
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:SIM_ABSENT
+     */
+    void sendEnvelopeWithStatusResponse(in RadioResponseInfo info, in IccIoResult iccIo);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:SIM_ABSENT
+     */
+    void sendTerminalResponseToSimResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void setAllowedCarriersResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:RIL_E_SUCCESS
+     *   RadioError:RIL_E_RADIO_NOT_AVAILABLE
+     *   RadioError:SIM_ABSENT
+     *   RadioError:RIL_E_REQUEST_NOT_SUPPORTED
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:MODEM_INTERNAL_FAILURE
+     */
+    void setCarrierInfoForImsiEncryptionResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:SIM_ABSENT
+     *   RadioError:SUBSCRIPTION_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void setCdmaSubscriptionSourceResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param retry 0 is the number of retries remaining, or -1 if unknown
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:SS_MODIFIED_TO_DIAL
+     *   RadioError:SS_MODIFIED_TO_USSD
+     *   RadioError:SS_MODIFIED_TO_SS
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:NO_MEMORY
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:INVALID_STATE
+     *   RadioError:FDN_CHECK_FAILURE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void setFacilityLockForAppResponse(in RadioResponseInfo info, in int retry);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:SIM_ERR (indicates a timeout or other issue making the SIM unresponsive)
+     */
+    void setSimCardPowerResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:SUBSCRIPTION_NOT_SUPPORTED
+     *   RadioError:NO_MEMORY
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:MODEM_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void setUiccSubscriptionResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param remainingRetries Number of retries remaining, must be equal to -1 if unknown.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE (radio resetting)
+     *   RadioError:PASSWORD_INCORRECT
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_SIM_STATE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:SIM_PUK2
+     */
+    void supplyIccPin2ForAppResponse(in RadioResponseInfo info, in int remainingRetries);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param remainingRetries Number of retries remaining, must be equal to -1 if unknown.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE (radio resetting)
+     *   RadioError:PASSWORD_INCORRECT
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_SIM_STATE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void supplyIccPinForAppResponse(in RadioResponseInfo info, in int remainingRetries);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param remainingRetries Number of retries remaining, must be equal to -1 if unknown.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE (radio resetting)
+     *   RadioError:PASSWORD_INCORRECT (PUK is invalid)
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_SIM_STATE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void supplyIccPuk2ForAppResponse(in RadioResponseInfo info, in int remainingRetries);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param remainingRetries Number of retries remaining, must be equal to -1 if unknown.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE (radio resetting)
+     *   RadioError:PASSWORD_INCORRECT (PUK is invalid)
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_SIM_STATE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void supplyIccPukForAppResponse(in RadioResponseInfo info, in int remainingRetries);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param persoType SIM Personalization type
+     * @param remainingRetries postiive values indicates number of retries remaining, must be equal
+     *        to -1 if number of retries is infinite.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:PASSWORD_INCORRECT (code is invalid)
+     *   RadioError:NO_MEMORY
+     *   RadioError:INVALID_SIM_STATE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:MODEM_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:NO_RESOURCES
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void supplySimDepersonalizationResponse(
+            in RadioResponseInfo info, in PersoSubstate persoType, in int remainingRetries);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param updatedRecordIndex The index of the updated or inserted record in the phonebook and
+     *        the minimum value is 1
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_SIM_STATE
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SIM_ERR
+     *   RadioError:NO_SUCH_ENTRY
+     *   RadioError:NO_RESOURCES
+     * REQUEST_NOT_SUPPORTED may only be returned on devices that don't support this API,
+     * indicated by the HAL capability CAPABILITY_SIM_PHONEBOOK_IN_MODEM.
+     */
+    void updateSimPhonebookRecordsResponse(in RadioResponseInfo info, in int updatedRecordIndex);
+}
diff --git a/radio/aidl/android/hardware/radio/sim/IccIo.aidl b/radio/aidl/android/hardware/radio/sim/IccIo.aidl
new file mode 100644
index 0000000..f173c8e
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/sim/IccIo.aidl
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.sim;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable IccIo {
+    /**
+     * One of the commands listed for TS 27.007 +CRSM
+     */
+    int command;
+    /**
+     * EF ID
+     */
+    int fileId;
+    /**
+     * "pathid" from TS 27.007 +CRSM command. Path is in hex ASCII format eg "7f205f70"
+     * Path must always be provided.
+     */
+    String path;
+    /**
+     * Value of p1 defined as per 3GPP TS 51.011
+     */
+    int p1;
+    /**
+     * Value of p2 defined as per 3GPP TS 51.011
+     */
+    int p2;
+    /**
+     * Value of p3 defined as per 3GPP TS 51.011
+     */
+    int p3;
+    /**
+     * Information to be written to the SIM
+     */
+    String data;
+    String pin2;
+    /**
+     * AID value, See ETSI 102.221 8.1 and 101.220 4, empty string if no value.
+     */
+    String aid;
+}
diff --git a/radio/aidl/android/hardware/radio/sim/IccIoResult.aidl b/radio/aidl/android/hardware/radio/sim/IccIoResult.aidl
new file mode 100644
index 0000000..efcbbda
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/sim/IccIoResult.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.sim;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable IccIoResult {
+    int sw1;
+    int sw2;
+    /**
+     * In hex string format ([a-fA-F0-9]*), except for SIM_AUTHENTICATION response for which it is
+     * in Base64 format, see 3GPP TS 31.102 7.1.2
+     */
+    String simResponse;
+}
diff --git a/radio/aidl/android/hardware/radio/sim/ImsiEncryptionInfo.aidl b/radio/aidl/android/hardware/radio/sim/ImsiEncryptionInfo.aidl
new file mode 100644
index 0000000..ba1dda5
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/sim/ImsiEncryptionInfo.aidl
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.sim;
+
+/**
+ * Carrier specific Information sent by the carrier, which will be used to encrypt IMSI and IMPI.
+ */
+@VintfStability
+@JavaDerive(toString=true)
+parcelable ImsiEncryptionInfo {
+    /**
+     * Key type to be used for ePDG
+     */
+    const byte PUBLIC_KEY_TYPE_EPDG = 1;
+    /**
+     * Key type to be used for WLAN
+     */
+    const byte PUBLIC_KEY_TYPE_WLAN = 2;
+
+    /**
+     * MCC of the Carrier.
+     */
+    String mcc;
+    /**
+     * MNC of the Carrier.
+     */
+    String mnc;
+    /**
+     * Carrier specific key to be used for encryption. It must be opaque to the framework.
+     * This is the byte-stream representation of the key. This is an external encoded form for the
+     * key used when a standard representation of the key is needed outside the Java Virtual
+     * Machine, as when transmitting the key to some other party. The key is encoded according to a
+     * standard format (such as X.509 SubjectPublicKeyInfo or PKCS#8), and is returned using the
+     * getEncoded method as defined on the java.security.Key interface.
+     */
+    byte[] carrierKey;
+    /**
+     * This is an opaque value we're given by the carrier and is returned to the carrier.
+     * This is used by the server to help it locate the private key to decrypt the
+     * permanent identity.
+     */
+    String keyIdentifier;
+    /**
+     * Date-time in UTC when the key will expire.
+     */
+    long expirationTime;
+    /**
+     * Public key type from carrier certificate.
+     * Values are PUBLIC_KEY_TYPE_
+     */
+    byte keyType;
+}
diff --git a/radio/aidl/android/hardware/radio/sim/PbReceivedStatus.aidl b/radio/aidl/android/hardware/radio/sim/PbReceivedStatus.aidl
new file mode 100644
index 0000000..b1385a4
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/sim/PbReceivedStatus.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.sim;
+
+/**
+ * Enum representing the status of the received PB indication.
+ */
+@VintfStability
+@Backing(type="byte")
+@JavaDerive(toString=true)
+enum PbReceivedStatus {
+    /**
+     * Indicates that retrieval is fine.
+     */
+    PB_RECEIVED_OK = 1,
+    /**
+     * Indicates that an error happened. In general, the process can't be restored soon.
+     */
+    PB_RECEIVED_ERROR = 2,
+    /**
+     * Indicates that the process is interrupted. In this case, the modem might need resources and
+     * interrupt the current process, or it is timed out to receive all indications, and client can
+     * retry soon.
+     */
+    PB_RECEIVED_ABORT = 3,
+    /**
+     * Indicates that the whole process is finished with a full chunk of phonebook data, meaning
+     * this is the last indication with the remaining data.
+     */
+    PB_RECEIVED_FINAL = 4,
+}
diff --git a/radio/aidl/android/hardware/radio/sim/PersoSubstate.aidl b/radio/aidl/android/hardware/radio/sim/PersoSubstate.aidl
new file mode 100644
index 0000000..f85c84b
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/sim/PersoSubstate.aidl
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.sim;
+
+/**
+ * Additional personalization categories in addition to those specified in 3GPP TS 22.022 and
+ * 3GPP2 C.S0068-0.
+ */
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum PersoSubstate {
+    /**
+     * Initial state
+     */
+    UNKNOWN,
+    /**
+     * In between each lock transition
+     */
+    IN_PROGRESS,
+    /**
+     * When either SIM or RUIM Perso is finished since each app must only have 1 active perso
+     * involved.
+     */
+    READY,
+    SIM_NETWORK,
+    SIM_NETWORK_SUBSET,
+    SIM_CORPORATE,
+    SIM_SERVICE_PROVIDER,
+    SIM_SIM,
+    /**
+     * The corresponding perso lock is blocked
+     */
+    SIM_NETWORK_PUK,
+    SIM_NETWORK_SUBSET_PUK,
+    SIM_CORPORATE_PUK,
+    SIM_SERVICE_PROVIDER_PUK,
+    SIM_SIM_PUK,
+    RUIM_NETWORK1,
+    RUIM_NETWORK2,
+    RUIM_HRPD,
+    RUIM_CORPORATE,
+    RUIM_SERVICE_PROVIDER,
+    RUIM_RUIM,
+    /**
+     * The corresponding perso lock is blocked
+     */
+    RUIM_NETWORK1_PUK,
+    RUIM_NETWORK2_PUK,
+    RUIM_HRPD_PUK,
+    RUIM_CORPORATE_PUK,
+    RUIM_SERVICE_PROVIDER_PUK,
+    RUIM_RUIM_PUK,
+    /**
+     * The device is personalized using the content of the Service Provider Name (SPN) in the SIM
+     * card.
+     */
+    SIM_SPN,
+    SIM_SPN_PUK,
+    /**
+     * Service Provider and Equivalent Home PLMN. The device is personalized using both the content
+     * of the GID1 (equivalent to service provider personalization) and the content of the
+     * Equivalent Home PLMN (EHPLMN) in the SIM card. If the GID1 in the SIM is absent, then just
+     * the content of the Equivalent Home PLMN is matched.
+     */
+    SIM_SP_EHPLMN,
+    SIM_SP_EHPLMN_PUK,
+    /**
+     * Device is personalized using the first digits of the ICCID of the SIM card.
+     */
+    SIM_ICCID,
+    SIM_ICCID_PUK,
+    /**
+     * Device is personalized using the content of the IMPI in the ISIM.
+     */
+    SIM_IMPI,
+    SIM_IMPI_PUK,
+    /**
+     * Network Subset and Service Provider. Device is personalized using both the content of GID1
+     * (equivalent to service provider personalization) and the first digits of the IMSI (equivalent
+     * to network subset personalization).
+     */
+    SIM_NS_SP,
+    SIM_NS_SP_PUK,
+}
diff --git a/radio/aidl/android/hardware/radio/sim/PhonebookCapacity.aidl b/radio/aidl/android/hardware/radio/sim/PhonebookCapacity.aidl
new file mode 100644
index 0000000..97c3dba
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/sim/PhonebookCapacity.aidl
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.sim;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable PhonebookCapacity {
+    /**
+     * Maximum number of ADN records possible in the SIM phonebook. Needs to be non-negative.
+     */
+    int maxAdnRecords;
+    /**
+     * Used ADN records in the SIM phonebook. Needs to be non-negative.
+     */
+    int usedAdnRecords;
+    /**
+     * Maximum email records possible in the SIM phonebook. Needs to be non-negative.
+     */
+    int maxEmailRecords;
+    /**
+     * Used email records in the SIM phonebook. Needs to be non-negative.
+     */
+    int usedEmailRecords;
+    /**
+     * Maximum additional number records possible in the SIM phonebook. Needs to be non-negative.
+     */
+    int maxAdditionalNumberRecords;
+    /**
+     * Used additional number records in the SIM phonebook. Needs to be non-negative.
+     */
+    int usedAdditionalNumberRecords;
+    /**
+     * Maximum name length possible in the SIM phonebook. Needs to be non-negative.
+     */
+    int maxNameLen;
+    /**
+     * Maximum number length possible in the SIM phonebook. Needs to be non-negative.
+     */
+    int maxNumberLen;
+    /**
+     * Maximum email length possible in the SIM phonebook. Needs to be non-negative.
+     */
+    int maxEmailLen;
+    /**
+     * Maximum additional number length possible in the SIM phonebook. Needs to be non-negative.
+     */
+    int maxAdditionalNumberLen;
+}
diff --git a/radio/aidl/android/hardware/radio/sim/PhonebookRecordInfo.aidl b/radio/aidl/android/hardware/radio/sim/PhonebookRecordInfo.aidl
new file mode 100644
index 0000000..c4db0e6
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/sim/PhonebookRecordInfo.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.sim;
+
+/**
+ * Phonebook-record-information specified by EF_ADN (Abbreviated dialing numbers) record of SIM
+ * as per 3GPP spec 31.102 v15 Section-4.4.2.3.
+ */
+@VintfStability
+@JavaDerive(toString=true)
+parcelable PhonebookRecordInfo {
+    /**
+     * Record index. 0 is used to insert a record
+     */
+    int recordId;
+    /**
+     * Alpha identifier, empty string if no value
+     */
+    String name;
+    /**
+     * Dialling number, empty string if no value
+     */
+    String number;
+    /**
+     * Email addresses
+     */
+    String[] emails;
+    /**
+     * Additional numbers
+     */
+    String[] additionalNumbers;
+}
diff --git a/radio/aidl/android/hardware/radio/sim/PinState.aidl b/radio/aidl/android/hardware/radio/sim/PinState.aidl
new file mode 100644
index 0000000..85048bb
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/sim/PinState.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.sim;
+
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum PinState {
+    UNKNOWN,
+    ENABLED_NOT_VERIFIED,
+    ENABLED_VERIFIED,
+    DISABLED,
+    ENABLED_BLOCKED,
+    ENABLED_PERM_BLOCKED,
+}
diff --git a/radio/aidl/android/hardware/radio/sim/SelectUiccSub.aidl b/radio/aidl/android/hardware/radio/sim/SelectUiccSub.aidl
new file mode 100644
index 0000000..553404b
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/sim/SelectUiccSub.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.sim;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable SelectUiccSub {
+    const int SUBSCRIPTION_TYPE_1 = 0;
+    const int SUBSCRIPTION_TYPE_2 = 1;
+    const int SUBSCRIPTION_TYPE_3 = 2;
+
+    const int ACT_STATUS_DEACTIVATE = 0;
+    const int ACT_STATUS_ACTIVATE = 1;
+
+    int slot;
+    /**
+     * Array subscriptor from applications[RadioConst:CARD_MAX_APPS] in getIccCardStatus()
+     */
+    int appIndex;
+    /**
+     * Values are SUBSCRIPTION_TYPE_
+     */
+    int subType;
+    /**
+     * Values are ACT_STATUS_
+     */
+    int actStatus;
+}
diff --git a/radio/aidl/android/hardware/radio/sim/SimApdu.aidl b/radio/aidl/android/hardware/radio/sim/SimApdu.aidl
new file mode 100644
index 0000000..43adbbc
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/sim/SimApdu.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.sim;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable SimApdu {
+    /**
+     * "sessionid" from TS 27.007 +CGLA command. Must be ignored for +CSIM command.
+     */
+    int sessionId;
+    /**
+     * Used to derive the APDU ("command" and "length" values in TS 27.007 +CSIM and +CGLA commands)
+     */
+    int cla;
+    /**
+     * Used to derive the APDU ("command" and "length" values in TS 27.007 +CSIM and +CGLA commands)
+     */
+    int instruction;
+    /**
+     * Used to derive the APDU ("command" and "length" values in TS 27.007 +CSIM and +CGLA commands)
+     */
+    int p1;
+    /**
+     * Used to derive the APDU ("command" and "length" values in TS 27.007 +CSIM and +CGLA commands)
+     */
+    int p2;
+    /**
+     * Used to derive the APDU ("command" and "length" values in TS 27.007 +CSIM and +CGLA commands)
+     * A negative P3 implies a 4 byte APDU.
+     */
+    int p3;
+    /**
+     * Used to derive the APDU ("command" and "length" values in TS 27.007 +CSIM and +CGLA commands)
+     * In hex string format ([a-fA-F0-9]*)
+     */
+    String data;
+}
diff --git a/radio/aidl/android/hardware/radio/sim/SimLockMultiSimPolicy.aidl b/radio/aidl/android/hardware/radio/sim/SimLockMultiSimPolicy.aidl
new file mode 100644
index 0000000..6490d51
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/sim/SimLockMultiSimPolicy.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.sim;
+
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum SimLockMultiSimPolicy {
+    /**
+     * Indicates that configuration applies to each slot independently.
+     */
+    NO_MULTISIM_POLICY,
+    /**
+     * Indicates that any SIM card can be used as far as one valid card is present in the device.
+     * For the modem, a SIM card is valid when its content (i.e. MCC, MNC, GID, SPN) matches the
+     * carrier restriction configuration.
+     */
+    ONE_VALID_SIM_MUST_BE_PRESENT,
+}
diff --git a/radio/aidl/android/hardware/radio/sim/SimRefreshResult.aidl b/radio/aidl/android/hardware/radio/sim/SimRefreshResult.aidl
new file mode 100644
index 0000000..69aff66
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/sim/SimRefreshResult.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.sim;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable SimRefreshResult {
+    /**
+     * A file on SIM has been updated.
+     */
+    const int TYPE_SIM_FILE_UPDATE = 0;
+    /**
+     * SIM initialized. All files should be re-read.
+     */
+    const int TYPE_SIM_INIT = 1;
+    /**
+     * SIM reset. SIM power required, SIM may be locked and all files must be re-read.
+     */
+    const int TYPE_SIM_RESET = 2;
+
+    /**
+     * Values are TYPE_SIM_
+     */
+    int type;
+    /**
+     * EFID of the updated file if the result is SIM_FILE_UPDATE or 0 for any other result.
+     */
+    int efId;
+    /**
+     * AID (application ID) of the card application. See ETSI 102.221 8.1 and 101.220 4.
+     * For TYPE_SIM_FILE_UPDATE result, it must be set to AID of application in which updated EF
+     * resides or it must be empty string if EF is outside of an application. For TYPE_SIM_INIT
+     * result, this field is set to AID of application that caused REFRESH. For TYPE_SIM_RESET
+     * result, it is empty string.
+     */
+    String aid;
+}
diff --git a/radio/aidl/android/hardware/radio/voice/AudioQuality.aidl b/radio/aidl/android/hardware/radio/voice/AudioQuality.aidl
new file mode 100644
index 0000000..dc47172
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/voice/AudioQuality.aidl
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.voice;
+
+/**
+ * Audio codec which is used on GSM, UMTS, and CDMA. These values must be opaque to the Android
+ * framework. Only for display.
+ */
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum AudioQuality {
+    /**
+     * Unspecified audio codec
+     */
+    UNSPECIFIED,
+    /**
+     * AMR (Narrowband) audio codec
+     */
+    AMR,
+    /**
+     * AMR (Wideband) audio codec
+     */
+    AMR_WB,
+    /**
+     * GSM Enhanced Full-Rate audio codec
+     */
+    GSM_EFR,
+    /**
+     * GSM Full-Rate audio codec
+     */
+    GSM_FR,
+    /**
+     * GSM Half-Rate audio codec
+     */
+    GSM_HR,
+    /**
+     * Enhanced Variable rate codec
+     */
+    EVRC,
+    /**
+     * Enhanced Variable rate codec revision B
+     */
+    EVRC_B,
+    /**
+     * Enhanced Variable rate codec (Wideband)
+     */
+    EVRC_WB,
+    /**
+     * Enhanced Variable rate codec (Narrowband)
+     */
+    EVRC_NW,
+}
diff --git a/radio/aidl/android/hardware/radio/voice/Call.aidl b/radio/aidl/android/hardware/radio/voice/Call.aidl
new file mode 100644
index 0000000..b09d7a0
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/voice/Call.aidl
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.voice;
+
+import android.hardware.radio.voice.AudioQuality;
+import android.hardware.radio.voice.UusInfo;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable Call {
+    const int PRESENTATION_ALLOWED = 0;
+    const int PRESENTATION_RESTRICTED = 1;
+    const int PRESENTATION_UNKNOWN = 2;
+    const int PRESENTATION_PAYPHONE = 3;
+
+    const int STATE_ACTIVE = 0;
+    const int STATE_HOLDING = 1;
+    /**
+     * MO call only
+     */
+    const int STATE_DIALING = 2;
+    /**
+     * MO call only
+     */
+    const int STATE_ALERTING = 3;
+    /**
+     * MT call only
+     */
+    const int STATE_INCOMING = 4;
+    /**
+     * MT call only
+     */
+    const int STATE_WAITING = 5;
+
+    /**
+     * Values are STATE_
+     */
+    int state;
+    /**
+     * Connection index for use with, eg, AT+CHLD
+     */
+    int index;
+    /**
+     * Type of address, eg 145 = intl
+     */
+    int toa;
+    /**
+     * true if is mpty call
+     */
+    boolean isMpty;
+    /**
+     * true if call is mobile terminated
+     */
+    boolean isMT;
+    /**
+     * ALS line indicator if availale (0 = line 1)
+     */
+    byte als;
+    /**
+     * true if this is a voice call
+     */
+    boolean isVoice;
+    /**
+     * true if CDMA voice privacy mode is active
+     */
+    boolean isVoicePrivacy;
+    /**
+     * Remote party nummber
+     */
+    String number;
+    /**
+     * Values are PRESENTATION_
+     */
+    int numberPresentation;
+    /**
+     * Remote party name
+     */
+    String name;
+    /**
+     * Values are PRESENTATION_
+     */
+    int namePresentation;
+    /**
+     * Vector of User-User Signaling Information
+     */
+    UusInfo[] uusInfo;
+    AudioQuality audioQuality;
+    /**
+     * Forwarded number. It can set only one forwarded number based on 3GPP rule of the CS.
+     * Reference: 3GPP TS 24.008 section 10.5.4.21b
+     */
+    String forwardedNumber;
+}
diff --git a/radio/aidl/android/hardware/radio/voice/CallForwardInfo.aidl b/radio/aidl/android/hardware/radio/voice/CallForwardInfo.aidl
new file mode 100644
index 0000000..c4143b9
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/voice/CallForwardInfo.aidl
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.voice;
+
+/**
+ * See also com.android.internal.telephony.gsm.CallForwardInfo
+ */
+@VintfStability
+@JavaDerive(toString=true)
+parcelable CallForwardInfo {
+    const int STATUS_DISABLE = 0;
+    const int STATUS_ENABLE = 1;
+    const int STATUS_INTERROGATE = 2;
+    const int STATUS_REGISTRATION = 3;
+    const int STATUS_ERASURE = 4;
+
+    /**
+     * For queryCallForwardStatus() status is STATUS_DISABLE (Not used by vendor code currently)
+     * For setCallForward() status must be STATUS_DISABLE, STATUS_ENABLE, STATUS_INTERROGATE,
+     * STATUS_REGISTRATION, STATUS_ERASURE
+     * Values are STATUS_
+     */
+    int status;
+    /**
+     * From TS 27.007 7.11 "reason"
+     */
+    int reason;
+    /**
+     * From TS 27.007 +CCFC/+CLCK "class". See table for Android mapping from MMI service code.
+     * 0 means user doesn't input class.
+     */
+    int serviceClass;
+    /**
+     * From TS 27.007 7.11 "type"
+     */
+    int toa;
+    /**
+     * From TS 27.007 7.11 "number"
+     */
+    String number;
+    int timeSeconds;
+}
diff --git a/radio/aidl/android/hardware/radio/voice/CdmaCallWaiting.aidl b/radio/aidl/android/hardware/radio/voice/CdmaCallWaiting.aidl
new file mode 100644
index 0000000..4d447d7
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/voice/CdmaCallWaiting.aidl
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.voice;
+
+import android.hardware.radio.voice.CdmaSignalInfoRecord;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable CdmaCallWaiting {
+    const int NUMBER_PLAN_UNKNOWN = 0;
+    const int NUMBER_PLAN_ISDN = 1;
+    const int NUMBER_PLAN_DATA = 3;
+    const int NUMBER_PLAN_TELEX = 4;
+    const int NUMBER_PLAN_NATIONAL = 8;
+    const int NUMBER_PLAN_PRIVATE = 9;
+
+    const int NUMBER_PRESENTATION_ALLOWED = 0;
+    const int NUMBER_PRESENTATION_RESTRICTED = 1;
+    const int NUMBER_PRESENTATION_UNKNOWN = 2;
+
+    const int NUMBER_TYPE_UNKNOWN = 0;
+    const int NUMBER_TYPE_INTERNATIONAL = 1;
+    const int NUMBER_TYPE_NATIONAL = 2;
+    const int NUMBER_TYPE_NETWORK_SPECIFIC = 3;
+    const int NUMBER_TYPE_SUBSCRIBER = 4;
+
+    /**
+     * Remote party number
+     */
+    String number;
+    /**
+     * Values are NUMBER_PRESENTATION_
+     */
+    int numberPresentation;
+    /**
+     * Remote party name
+     */
+    String name;
+    CdmaSignalInfoRecord signalInfoRecord;
+    /**
+     * Required to support International Call Waiting
+     * Values are NUMBER_TYPE_
+     */
+    int numberType;
+    /**
+     * Required to support International Call Waiting
+     * Values are NUMBER_PLAN_
+     */
+    int numberPlan;
+}
diff --git a/radio/aidl/android/hardware/radio/voice/CdmaDisplayInfoRecord.aidl b/radio/aidl/android/hardware/radio/voice/CdmaDisplayInfoRecord.aidl
new file mode 100644
index 0000000..522f7ae
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/voice/CdmaDisplayInfoRecord.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.voice;
+
+/**
+ * Display Info Rec as defined in C.S0005 section 3.7.5.1. Extended Display Info Rec as defined in
+ * C.S0005 section 3.7.5.16. Note that the Extended Display info rec contains multiple records of
+ * the form: display_tag, display_len, and display_len occurrences of the char field if the
+ * display_tag is not 10000000 or 10000001. To save space, the records are stored consecutively in
+ * a byte buffer. The display_tag, display_len and chari fields are all 1 byte.
+ */
+@VintfStability
+@JavaDerive(toString=true)
+parcelable CdmaDisplayInfoRecord {
+    const int CDMA_ALPHA_INFO_BUFFER_LENGTH = 64;
+    /**
+     * Max length = CDMA_ALPHA_INFO_BUFFER_LENGTH
+     */
+    String alphaBuf;
+}
diff --git a/radio/aidl/android/hardware/radio/voice/CdmaInformationRecord.aidl b/radio/aidl/android/hardware/radio/voice/CdmaInformationRecord.aidl
new file mode 100644
index 0000000..1a4f1b3
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/voice/CdmaInformationRecord.aidl
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.voice;
+
+import android.hardware.radio.voice.CdmaDisplayInfoRecord;
+import android.hardware.radio.voice.CdmaLineControlInfoRecord;
+import android.hardware.radio.voice.CdmaNumberInfoRecord;
+import android.hardware.radio.voice.CdmaRedirectingNumberInfoRecord;
+import android.hardware.radio.voice.CdmaSignalInfoRecord;
+import android.hardware.radio.voice.CdmaT53AudioControlInfoRecord;
+import android.hardware.radio.voice.CdmaT53ClirInfoRecord;
+
+@VintfStability
+/**
+ * Max length of CdmaInformationRecords[] is CDMA_MAX_NUMBER_OF_INFO_RECS
+ */
+@JavaDerive(toString=true)
+parcelable CdmaInformationRecord {
+    const int CDMA_MAX_NUMBER_OF_INFO_RECS = 10;
+    /**
+     * Names of the CDMA info records (C.S0005 section 3.7.5)
+     */
+    const int NAME_DISPLAY = 0;
+    const int NAME_CALLED_PARTY_NUMBER = 1;
+    const int NAME_CALLING_PARTY_NUMBER = 2;
+    const int NAME_CONNECTED_NUMBER = 3;
+    const int NAME_SIGNAL = 4;
+    const int NAME_REDIRECTING_NUMBER = 5;
+    const int NAME_LINE_CONTROL = 6;
+    const int NAME_EXTENDED_DISPLAY = 7;
+    const int NAME_T53_CLIR = 8;
+    const int NAME_T53_RELEASE = 9;
+    const int NAME_T53_AUDIO_CONTROL = 10;
+
+    /**
+     * Based on CdmaInfoRecName, only one of the below vectors must have size = 1.
+     * All other vectors must have size 0.
+     * Values are NAME_
+     */
+    int name;
+    /**
+     * Display and extended display info rec
+     */
+    CdmaDisplayInfoRecord[] display;
+    /**
+     * Called party number, calling party number, connected number info rec
+     */
+    CdmaNumberInfoRecord[] number;
+    /**
+     * Signal info rec
+     */
+    CdmaSignalInfoRecord[] signal;
+    /**
+     * Redirecting number info rec
+     */
+    CdmaRedirectingNumberInfoRecord[] redir;
+    /**
+     * Line control info rec
+     */
+    CdmaLineControlInfoRecord[] lineCtrl;
+    /**
+     * T53 CLIR info rec
+     */
+    CdmaT53ClirInfoRecord[] clir;
+    /**
+     * T53 Audio Control info rec
+     */
+    CdmaT53AudioControlInfoRecord[] audioCtrl;
+}
diff --git a/radio/aidl/android/hardware/radio/voice/CdmaLineControlInfoRecord.aidl b/radio/aidl/android/hardware/radio/voice/CdmaLineControlInfoRecord.aidl
new file mode 100644
index 0000000..8bfc5f7
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/voice/CdmaLineControlInfoRecord.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.voice;
+
+/**
+ * Line Control Information Record as defined in C.S0005 section 3.7.5.15
+ */
+@VintfStability
+@JavaDerive(toString=true)
+parcelable CdmaLineControlInfoRecord {
+    byte lineCtrlPolarityIncluded;
+    byte lineCtrlToggle;
+    byte lineCtrlReverse;
+    byte lineCtrlPowerDenial;
+}
diff --git a/radio/aidl/android/hardware/radio/voice/CdmaNumberInfoRecord.aidl b/radio/aidl/android/hardware/radio/voice/CdmaNumberInfoRecord.aidl
new file mode 100644
index 0000000..9084b25
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/voice/CdmaNumberInfoRecord.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.voice;
+
+/**
+ * Called Party Number Info Rec as defined in C.S0005 section 3.7.5.2
+ * Calling Party Number Info Rec as defined in C.S0005 section 3.7.5.3
+ * Connected Number Info Rec as defined in C.S0005 section 3.7.5.4
+ */
+@VintfStability
+@JavaDerive(toString=true)
+parcelable CdmaNumberInfoRecord {
+    const int CDMA_NUMBER_INFO_BUFFER_LENGTH = 81;
+    /**
+     * Max length = CDMA_NUMBER_INFO_BUFFER_LENGTH
+     */
+    String number;
+    byte numberType;
+    byte numberPlan;
+    byte pi;
+    byte si;
+}
diff --git a/radio/aidl/android/hardware/radio/voice/CdmaOtaProvisionStatus.aidl b/radio/aidl/android/hardware/radio/voice/CdmaOtaProvisionStatus.aidl
new file mode 100644
index 0000000..81fb003
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/voice/CdmaOtaProvisionStatus.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.voice;
+
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum CdmaOtaProvisionStatus {
+    SPL_UNLOCKED,
+    SPC_RETRIES_EXCEEDED,
+    A_KEY_EXCHANGED,
+    SSD_UPDATED,
+    NAM_DOWNLOADED,
+    MDN_DOWNLOADED,
+    IMSI_DOWNLOADED,
+    PRL_DOWNLOADED,
+    COMMITTED,
+    OTAPA_STARTED,
+    OTAPA_STOPPED,
+    OTAPA_ABORTED,
+}
diff --git a/radio/aidl/android/hardware/radio/voice/CdmaRedirectingNumberInfoRecord.aidl b/radio/aidl/android/hardware/radio/voice/CdmaRedirectingNumberInfoRecord.aidl
new file mode 100644
index 0000000..5c9e2f2
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/voice/CdmaRedirectingNumberInfoRecord.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.voice;
+
+import android.hardware.radio.voice.CdmaNumberInfoRecord;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable CdmaRedirectingNumberInfoRecord {
+    /**
+     * Redirecting Number Information Record as defined in C.S0005 section 3.7.5.11
+     */
+    const int REDIRECTING_REASON_UNKNOWN = 0;
+    const int REDIRECTING_REASON_CALL_FORWARDING_BUSY = 1;
+    const int REDIRECTING_REASON_CALL_FORWARDING_NO_REPLY = 2;
+    const int REDIRECTING_REASON_CALLED_DTE_OUT_OF_ORDER = 9;
+    const int REDIRECTING_REASON_CALL_FORWARDING_BY_THE_CALLED_DTE = 10;
+    const int REDIRECTING_REASON_CALL_FORWARDING_UNCONDITIONAL = 15;
+    const int REDIRECTING_REASON_RESERVED = 16;
+
+    CdmaNumberInfoRecord redirectingNumber;
+    /**
+     * Set to UNKNOWN if not included.
+     * Values are REDIRECTING_REASON_
+     */
+    int redirectingReason;
+}
diff --git a/radio/aidl/android/hardware/radio/voice/CdmaSignalInfoRecord.aidl b/radio/aidl/android/hardware/radio/voice/CdmaSignalInfoRecord.aidl
new file mode 100644
index 0000000..3334475
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/voice/CdmaSignalInfoRecord.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.voice;
+
+/**
+ * CDMA Signal Information Record as defined in C.S0005 section 3.7.5.5
+ */
+@VintfStability
+@JavaDerive(toString=true)
+parcelable CdmaSignalInfoRecord {
+    /**
+     * True if signal information record is present
+     */
+    boolean isPresent;
+    /**
+     * Defined in 3.7.5.5-1
+     */
+    byte signalType;
+    /**
+     * Defined in 3.7.5.5-2
+     */
+    byte alertPitch;
+    /**
+     * Defined in 3.7.5.5-3, 3.7.5.5-4 or 3.7.5.5-5
+     */
+    byte signal;
+}
diff --git a/radio/aidl/android/hardware/radio/voice/CdmaT53AudioControlInfoRecord.aidl b/radio/aidl/android/hardware/radio/voice/CdmaT53AudioControlInfoRecord.aidl
new file mode 100644
index 0000000..9795cf0
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/voice/CdmaT53AudioControlInfoRecord.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.voice;
+
+/**
+ * T53 Audio Control Information Record
+ */
+@VintfStability
+@JavaDerive(toString=true)
+parcelable CdmaT53AudioControlInfoRecord {
+    byte upLink;
+    byte downLink;
+}
diff --git a/radio/aidl/android/hardware/radio/voice/CdmaT53ClirInfoRecord.aidl b/radio/aidl/android/hardware/radio/voice/CdmaT53ClirInfoRecord.aidl
new file mode 100644
index 0000000..5ccd251
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/voice/CdmaT53ClirInfoRecord.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.voice;
+
+/**
+ * T53 CLIR Information Record
+ */
+@VintfStability
+@JavaDerive(toString=true)
+parcelable CdmaT53ClirInfoRecord {
+    byte cause;
+}
diff --git a/radio/aidl/android/hardware/radio/voice/CfData.aidl b/radio/aidl/android/hardware/radio/voice/CfData.aidl
new file mode 100644
index 0000000..8f4c227
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/voice/CfData.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.voice;
+
+import android.hardware.radio.voice.CallForwardInfo;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable CfData {
+    const int NUM_SERVICE_CLASSES = 7;
+    /**
+     * This is the response data for SS request to query call forward status.
+     * See getCallForwardStatus(). Max size = NUM_SERVICE_CLASSES.
+     */
+    CallForwardInfo[] cfInfo;
+}
diff --git a/radio/aidl/android/hardware/radio/voice/ClipStatus.aidl b/radio/aidl/android/hardware/radio/voice/ClipStatus.aidl
new file mode 100644
index 0000000..4021471
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/voice/ClipStatus.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.voice;
+
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum ClipStatus {
+    /**
+     * CLIP provisioned
+     */
+    CLIP_PROVISIONED,
+    /**
+     * CLIP not provisioned
+     */
+    CLIP_UNPROVISIONED,
+    /**
+     * Unknown, e.g. no networks etc
+     */
+    UNKNOWN,
+}
diff --git a/radio/aidl/android/hardware/radio/voice/Dial.aidl b/radio/aidl/android/hardware/radio/voice/Dial.aidl
new file mode 100644
index 0000000..ca028ad
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/voice/Dial.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.voice;
+
+import android.hardware.radio.voice.UusInfo;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable Dial {
+    /**
+     * Use subscription default value
+     */
+    const int CLIR_DEFAULT = 0;
+    /**
+     * Restrict CLI presentation
+     */
+    const int CLIR_INVOCATION = 1;
+    /**
+     * Allow CLI presentation
+     */
+    const int CLIR_SUPPRESSION = 2;
+
+    String address;
+    /**
+     * Values are CLIR_
+     */
+    int clir;
+    /**
+     * Vector of User-User Signaling Information
+     */
+    UusInfo[] uusInfo;
+}
diff --git a/radio/aidl/android/hardware/radio/voice/EmergencyCallRouting.aidl b/radio/aidl/android/hardware/radio/voice/EmergencyCallRouting.aidl
new file mode 100644
index 0000000..d623346
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/voice/EmergencyCallRouting.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.voice;
+
+/**
+ * Indicates how the implementation should handle the emergency call if it is required by Android.
+ */
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum EmergencyCallRouting {
+    /**
+     * Indicates Android does not require how to handle the corresponding emergency call; it is
+     * decided by implementation.
+     */
+    UNKNOWN,
+    /**
+     * Indicates the implementation must handle the call through emergency routing.
+     */
+    EMERGENCY,
+    /**
+     * Indicates the implementation must handle the call through normal call routing.
+     */
+    NORMAL,
+}
diff --git a/radio/aidl/android/hardware/radio/voice/EmergencyNumber.aidl b/radio/aidl/android/hardware/radio/voice/EmergencyNumber.aidl
new file mode 100644
index 0000000..e380ce8
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/voice/EmergencyNumber.aidl
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.voice;
+
+/**
+ * Emergency number contains information of number, one or more service category(s), zero or more
+ * emergency uniform resource names, mobile country code (mcc), mobile network country (mnc) and
+ * source(s) that indicate where it comes from.
+ *
+ * If the emergency number is associated with country, field ‘mcc’ must be provided, otherwise
+ * field ‘mcc’ must be an empty string. If the emergency number is associated with network operator,
+ * field ‘mcc’ and 'mnc' must be provided, otherwise field ‘mnc’ must be an empty string. If the
+ * emergency number is specified with emergency service category(s), field 'categories' must be
+ * provided, otherwise field 'categories' must be EmergencyServiceCategories::UNSPECIFIED. If the
+ * emergency number is specified with emergency uniform resource names (URN), field 'urns' must be
+ * provided, otherwise field 'urns' must be an empty list.
+ *
+ * A unique EmergencyNumber has a unique combination of ‘number’, ‘mcc’, 'mnc', 'categories' and
+ * 'urns' fields. Multiple EmergencyNumberSource should be merged into one 'sources' field via
+ * bitwise-OR combination for the same EmergencyNumber.
+ *
+ * Reference: 3gpp 22.101, Section 10 - Emergency Calls;
+ *            3gpp 23.167, Section 6 - Functional description;
+ *            3gpp 24.503, Section 5.1.6.8.1 - General;
+ *            RFC 5031
+ */
+@VintfStability
+@JavaDerive(toString=true)
+parcelable EmergencyNumber {
+    /**
+     * Indicates the number is from the network signal.
+     */
+    const int SOURCE_NETWORK_SIGNALING = 1 << 0;
+    /**
+     * Indicates the number is from the sim card.
+     */
+    const int SOURCE_SIM = 1 << 1;
+    /**
+     * Indicates the number is from the modem config.
+     */
+    const int SOURCE_MODEM_CONFIG = 1 << 2;
+    /**
+     * Indicates the number is available as default. Per the reference, 112, 911 must always be
+     * available; additionally, 000, 08, 110, 999, 118 and 119 must be available when sim is not
+     * present.
+     */
+    const int SOURCE_DEFAULT = 1 << 3;
+
+    /**
+     * The emergency number. The character in the number string should only be the dial pad
+     * character('0'-'9', '*', or '#'). For example: 911.
+     */
+    String number;
+    /**
+     * 3-digit Mobile Country Code, 0..999. Empty string if not applicable.
+     */
+    String mcc;
+    /**
+     * 2 or 3-digit Mobile Network Code, 0..999. Empty string if not applicable.
+     */
+    String mnc;
+    /**
+     * The bitfield of EmergencyServiceCategory(s). See EmergencyServiceCategory for the value of
+     * each bit.
+     */
+    int categories;
+    /**
+     * The list of emergency Uniform Resource Names (URN).
+     */
+    String[] urns;
+    /**
+     * The bitfield of EmergencyNumberSource(s) to tell where the EmergencyNumber comes from.
+     * Reference: 3gpp 22.101, Section 10 - Emergency Calls
+     * Values are SOURCE_
+     */
+    int sources;
+}
diff --git a/radio/aidl/android/hardware/radio/voice/EmergencyServiceCategory.aidl b/radio/aidl/android/hardware/radio/voice/EmergencyServiceCategory.aidl
new file mode 100644
index 0000000..a4ac7aa
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/voice/EmergencyServiceCategory.aidl
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.voice;
+
+/**
+ * Defining Emergency Service Category as follows:
+ * - General emergency call, all categories;
+ * - Police;
+ * - Ambulance;
+ * - Fire Brigade;
+ * - Marine Guard;
+ * - Mountain Rescue;
+ * - Manually Initiated eCall (MIeC);
+ * - Automatically Initiated eCall (AIeC);
+ *
+ * Category UNSPECIFIED (General emergency call, all categories) indicates that no specific
+ * services are associated with this emergency number.
+ *
+ * Reference: 3gpp 22.101, Section 10 - Emergency Calls
+ */
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum EmergencyServiceCategory {
+    /**
+     * General emergency call, all categories
+     */
+    UNSPECIFIED = 0,
+    POLICE = 1 << 0,
+    AMBULANCE = 1 << 1,
+    FIRE_BRIGADE = 1 << 2,
+    MARINE_GUARD = 1 << 3,
+    MOUNTAIN_RESCUE = 1 << 4,
+    /**
+     * Manually Initiated eCall (MIeC)
+     */
+    MIEC = 1 << 5,
+    /**
+     * Automatically Initiated eCall (AIeC)
+     */
+    AIEC = 1 << 6,
+}
diff --git a/radio/aidl/android/hardware/radio/voice/IRadioVoice.aidl b/radio/aidl/android/hardware/radio/voice/IRadioVoice.aidl
new file mode 100644
index 0000000..c05d237
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/voice/IRadioVoice.aidl
@@ -0,0 +1,487 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.voice;
+
+import android.hardware.radio.voice.CallForwardInfo;
+import android.hardware.radio.voice.Dial;
+import android.hardware.radio.voice.EmergencyCallRouting;
+import android.hardware.radio.voice.IRadioVoiceIndication;
+import android.hardware.radio.voice.IRadioVoiceResponse;
+import android.hardware.radio.voice.TtyMode;
+
+/**
+ * This interface is used by telephony and telecom to talk to cellular radio for voice APIs.
+ * All the functions have minimum one parameter:
+ * serial: which corresponds to serial no. of request. Serial numbers must only be memorized for the
+ * duration of a method call. If clients provide colliding serials (including passing the same
+ * serial to different methods), multiple responses (one for each method call) must still be served.
+ * setResponseFunctions must work with IRadioVoiceResponse and IRadioVoiceIndication.
+ */
+@VintfStability
+oneway interface IRadioVoice {
+    /**
+     * Answer incoming call. Must not be called for WAITING calls.
+     * switchWaitingOrHoldingAndActive() must be used in this case instead
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioVoiceResponse.acceptCallResponse()
+     */
+    void acceptCall(in int serial);
+
+    /**
+     * Cancel the current USSD session if one exists.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioVoiceResponse.cancelPendingUssdResponse()
+     */
+    void cancelPendingUssd(in int serial);
+
+    /**
+     * Conference holding and active (like AT+CHLD=3)
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioVoiceResponse.conferenceResponse()
+     */
+    void conference(in int serial);
+
+    /**
+     * Initiate voice call. This method is never used for supplementary service codes.
+     *
+     * @param serial Serial number of request.
+     * @param dialInfo Dial struct
+     *
+     * Response function is IRadioVoiceResponse.dialResponse()
+     */
+    void dial(in int serial, in Dial dialInfo);
+
+    /**
+     * Initiate emergency voice call, with zero or more emergency service category(s), zero or
+     * more emergency Uniform Resource Names (URN), and routing information for handling the call.
+     * Android uses this request to make its emergency call instead of using IRadio.dial if the
+     * 'address' in the 'dialInfo' field is identified as an emergency number by Android.
+     *
+     * In multi-sim scenario, if the emergency number is from a specific subscription, this radio
+     * request can still be sent out on the other subscription as long as routing is set to
+     * EmergencyNumberRouting#EMERGENCY. This radio request will not be sent on an inactive
+     * (PIN/PUK locked) subscription unless both subscriptions are PIN/PUK locked. In this case,
+     * the request will be sent on the primary subscription.
+     *
+     * Some countries or carriers require some emergency numbers that must be handled with normal
+     * call routing if possible or emergency routing. 1) if the 'routing' field is specified as
+     * EmergencyNumberRouting#NORMAL, the implementation must try the full radio service to use
+     * normal call routing to handle the call; if service cannot support normal routing, the
+     * implementation must use emergency routing to handle the call. 2) if 'routing' is specified
+     * as EmergencyNumberRouting#EMERGENCY, the implementation must use emergency routing to handle
+     * the call. 3) if 'routing' is specified as EmergencyNumberRouting#UNKNOWN, Android does not
+     * know how to handle the call.
+     *
+     * If the dialed emergency number does not have a specified emergency service category, the
+     * 'categories' field is set to EmergencyServiceCategory#UNSPECIFIED; if the dialed emergency
+     * number does not have specified emergency Uniform Resource Names, the 'urns' field is set to
+     * an empty list. If the underlying technology used to request emergency services does not
+     * support the emergency service category or emergency uniform resource names, the field
+     * 'categories' or 'urns' may be ignored.
+     *
+     * In the scenarios that the 'address' in the 'dialInfo' field has other functions besides the
+     * emergency number function, if the 'hasKnownUserIntentEmergency' field is true, the user's
+     * intent for this dial request is emergency call, and the modem must treat this as an actual
+     * emergency dial; if the 'hasKnownUserIntentEmergency' field is false, Android does not know
+     * user's intent for this call.
+     *
+     * If 'isTesting' is true, this request is for testing purpose, and must not be sent to a real
+     * emergency service; otherwise it's for a real emergency call request.
+     *
+     * Reference: 3gpp 22.101, Section 10 - Emergency Calls;
+     *            3gpp 23.167, Section 6 - Functional description;
+     *            3gpp 24.503, Section 5.1.6.8.1 - General;
+     *            RFC 5031
+     *
+     * @param serial Serial number of request.
+     * @param dialInfo the same Dial information used by IRadioVoice.dial.
+     * @param categories bitfield<EmergencyServiceCategory> the Emergency Service Category(s)
+     *        of the call.
+     * @param urns the emergency Uniform Resource Names (URN)
+     * @param routing EmergencyCallRouting the emergency call routing information.
+     * @param hasKnownUserIntentEmergency Flag indicating if user's intent for the emergency call
+     *        is known.
+     * @param isTesting Flag indicating if this request is for testing purpose.
+     *
+     * Response function is IRadioVoiceResponse.emergencyDialResponse()
+     */
+    void emergencyDial(in int serial, in Dial dialInfo, in int categories, in String[] urns,
+            in EmergencyCallRouting routing, in boolean hasKnownUserIntentEmergency,
+            in boolean isTesting);
+
+    /**
+     * Request the radio's system selection module to exit emergency callback mode. Radio must not
+     * respond with SUCCESS until the modem has completely exited from Emergency Callback Mode.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioVoiceResponse.exitEmergencyCallbackModeResponse()
+     */
+    void exitEmergencyCallbackMode(in int serial);
+
+    /**
+     * Connects the two calls and disconnects the subscriber from both calls.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioVoiceResponse.explicitCallTransferResponse()
+     */
+    void explicitCallTransfer(in int serial);
+
+    /**
+     * Request call forward status.
+     *
+     * @param serial Serial number of request.
+     * @param callInfo CallForwardInfo
+     *
+     * Response function is IRadioVoiceResponse.getCallForwardStatusResponse()
+     */
+    void getCallForwardStatus(in int serial, in CallForwardInfo callInfo);
+
+    /**
+     * Query current call waiting state
+     *
+     * @param serial Serial number of request.
+     * @param serviceClass Service class is the TS 27.007 service class to query
+     *
+     * Response function is IRadioVoiceResponse.getCallWaitingResponse()
+     */
+    void getCallWaiting(in int serial, in int serviceClass);
+
+    /**
+     * Queries the status of the CLIP supplementary service (for MMI code "*#30#")
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioVoiceResponse.getClipResponse()
+     */
+    void getClip(in int serial);
+
+    /**
+     * Gets current CLIR status
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioVoiceResponse.getClirResponse()
+     */
+    void getClir(in int serial);
+
+    /**
+     * Requests current call list
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioVoiceResponse.getCurrentCallsResponse()
+     */
+    void getCurrentCalls(in int serial);
+
+    /**
+     * Requests the failure cause code for the most recently terminated call.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioVoiceResponse.getLastCallFailCauseResponse()
+     */
+    void getLastCallFailCause(in int serial);
+
+    /**
+     * Queries the current state of the uplink mute setting
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioVoiceResponse.getMuteResponse()
+     */
+    void getMute(in int serial);
+
+    /**
+     * Request the setting of preferred voice privacy mode.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioVoiceResponse.getPreferredVoicePrivacyResponse()
+     */
+    void getPreferredVoicePrivacy(in int serial);
+
+    /**
+     * Request the setting of TTY mode
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioVoiceResponse.getTtyModeResponse()
+     */
+    void getTtyMode(in int serial);
+
+    /**
+     * When STK application gets stkCallSetup(), the call actually has been initialized by the
+     * mobile device already. (We could see the call has been in the 'call list'). STK application
+     * needs to accept/reject the call according to user operations.
+     *
+     * @param serial Serial number of request.
+     * @param accept true = accept the call setup, false = reject the call setup
+     *
+     * Response function is IRadioVoiceResponse.handleStkCallSetupRequestFromSimResponse()
+     */
+    void handleStkCallSetupRequestFromSim(in int serial, in boolean accept);
+
+    /**
+     * Hang up a specific line (like AT+CHLD=1x). After this HANGUP request returns, Radio must
+     * show the connection is NOT active anymore in next getCurrentCalls() query.
+     *
+     * @param serial Serial number of request.
+     * @param gsmIndex Connection index (value of 'x' in CHLD above)
+     *
+     * Response function is IRadioVoiceResponse.hangupResponse()
+     */
+    void hangup(in int serial, in int gsmIndex);
+
+    /**
+     * Hang up waiting or held (like AT+CHLD=1). After this HANGUP request returns, Radio must show
+     * the connection is NOT active anymore in next getCurrentCalls() query.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioVoiceResponse.hangupForegroundResumeBackgroundResponse()
+     */
+    void hangupForegroundResumeBackground(in int serial);
+
+    /**
+     * Hang up waiting or held (like AT+CHLD=0). After this HANGUP request returns, Radio must show
+     * the connection is NOT active anymore in next getCurrentCalls() query.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioVoiceResponse.hangupWaitingOrBackgroundResponse()
+     */
+    void hangupWaitingOrBackground(in int serial);
+
+    /**
+     * Query current Voice NR enable state
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioVoiceResponse.isVoNrEnabledResponse()
+     */
+    void isVoNrEnabled(in int serial);
+
+    /**
+     * Send UDUB (user determined user busy) to ringing or waiting call answer)
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioVoiceResponse.rejectCallResponse()
+     */
+    void rejectCall(in int serial);
+
+    /**
+     * When response type received from a radio indication or radio response is
+     * RadioIndicationType:UNSOLICITED_ACK_EXP or RadioResponseType:SOLICITED_ACK_EXP respectively,
+     * acknowledge the receipt of those messages by sending responseAcknowledgement().
+     */
+    void responseAcknowledgement();
+
+    /**
+     * Send DTMF string
+     *
+     * @param serial Serial number of request.
+     * @param dtmf DTMF string
+     * @param on DTMF ON length in milliseconds, or 0 to use default
+     * @param off is the DTMF OFF length in milliseconds, or 0 to use default
+     *
+     * Response function is IRadioVoiceResponse.sendBurstDtmfResponse()
+     */
+    void sendBurstDtmf(in int serial, in String dtmf, in int on, in int off);
+
+    /**
+     * Send FLASH command
+     *
+     * @param serial Serial number of request.
+     * @param featureCode String associated with Flash command
+     *
+     * Response function is IRadioVoiceResponse.sendCdmaFeatureCodeResponse()
+     */
+    void sendCdmaFeatureCode(in int serial, in String featureCode);
+
+    /**
+     * Send a DTMF tone. If the implementation is currently playing a tone requested via
+     * startDtmf(), that tone must be cancelled and the new tone must be played instead.
+     *
+     * @param serial Serial number of request.
+     * @param s string with single char having one of 12 values: 0-9, *, #
+     *
+     * Response function is IRadioVoiceResponse.sendDtmfResponse()
+     */
+    void sendDtmf(in int serial, in String s);
+
+    /**
+     * Send a USSD message. If a USSD session already exists, the message must be sent in the
+     * context of that session. Otherwise, a new session must be created. The network reply must be
+     * reported via unsolOnUssd.
+     *
+     * Only one USSD session must exist at a time, and the session is assumed to exist until:
+     * a) The android system invokes cancelUssd()
+     * b) The implementation sends a unsolOnUssd() with a type code of
+     *    "0" (USSD-Notify/no further action) or "2" (session terminated)
+     *
+     * @param serial Serial number of request.
+     * @param ussd string containing the USSD request in UTF-8 format
+     *
+     * Response function is IRadioVoiceResponse.sendUssdResponse()
+     */
+    void sendUssd(in int serial, in String ussd);
+
+    /**
+     * Separate a party from a multiparty call placing the multiparty call (less the specified
+     * party) on hold and leaving the specified party as the only other member of the current
+     * (active) call. Like AT+CHLD=2x.
+     *
+     * See TS 22.084 1.3.8.2 (iii)
+     * TS 22.030 6.5.5 "Entering "2X followed by send"
+     * TS 27.007 "AT+CHLD=2x"
+     *
+     * @param serial Serial number of request.
+     * @param gsmIndex contains Connection index (value of 'x' in CHLD above)
+     *
+     * Response function is IRadioVoiceResponse.separateConnectionResponse()
+     */
+    void separateConnection(in int serial, in int gsmIndex);
+
+    /**
+     * Configure call forward rule
+     *
+     * @param serial Serial number of request.
+     * @param callInfo CallForwardInfo
+     *
+     * Response function is IRadioVoiceResponse.setCallForwardResponse()
+     */
+    void setCallForward(in int serial, in CallForwardInfo callInfo);
+
+    /**
+     * Configure current call waiting state
+     *
+     * @param serial Serial number of request.
+     * @param enable is false for "disabled" and true for "enabled"
+     * @param serviceClass is the TS 27.007 service class bit vector of services to modify
+     *
+     * Response function is IRadioVoiceResponse.setCallWaitingResponse()
+     */
+    void setCallWaiting(in int serial, in boolean enable, in int serviceClass);
+
+    /**
+     * Set current CLIR status
+     *
+     * @param serial Serial number of request.
+     * @param status "n" parameter from TS 27.007 7.7
+     *
+     * Response function is IRadioVoiceResponse.setClirResponse()
+     */
+    void setClir(in int serial, in int status);
+
+    /**
+     * Turn on or off uplink (microphone) mute. Must only be sent while voice call is active.
+     * Must always be reset to "disable mute" when a new voice call is initiated
+     *
+     * @param serial Serial number of request.
+     * @param enable true for "enable mute" and false for "disable mute"
+     *
+     * Response function is IRadioVoiceResponse.setMuteResponse()
+     */
+    void setMute(in int serial, in boolean enable);
+
+    /**
+     * Request to set the preferred voice privacy mode used in voice scrambling.
+     *
+     * @param serial Serial number of request.
+     * @param enable false for Standard Privacy Mode (Public Long Code Mask)
+     *        true for Enhanced Privacy Mode (Private Long Code Mask)
+     *
+     * Response function is IRadioVoiceResponse.setPreferredVoicePrivacyResponse()
+     */
+    void setPreferredVoicePrivacy(in int serial, in boolean enable);
+
+    /**
+     * Set response functions for voice radio requests and indications.
+     *
+     * @param radioVoiceResponse Object containing response functions
+     * @param radioVoiceIndication Object containing radio indications
+     */
+    void setResponseFunctions(in IRadioVoiceResponse radioVoiceResponse,
+            in IRadioVoiceIndication radioVoiceIndication);
+
+    /**
+     * Request to set the TTY mode
+     *
+     * @param serial Serial number of request.
+     * @param mode TtyMode
+     *
+     * Response function is IRadioVoiceResponse.setTtyModeResponse()
+     */
+    void setTtyMode(in int serial, in TtyMode mode);
+
+    /**
+     * Set Voice NR enable state
+     *
+     * @param serial Serial number of request.
+     * @param enable true for "enable vonr" and false for "disable vonr"
+     *
+     * Response function is IRadioVoiceResponse.setVoNrEnabledResponse()
+     */
+    void setVoNrEnabled(in int serial, in boolean enable);
+
+    /**
+     * Start playing a DTMF tone. Continue playing DTMF tone until stopDtmf is received. If a
+     * startDtmf() is received while a tone is currently playing, it must cancel the previous tone
+     * and play the new one.
+     *
+     * @param serial Serial number of request.
+     * @param s string having a single character with one of 12 values: 0-9,*,#
+     *
+     * Response function is IRadioVoiceResponse.startDtmfResponse()
+     */
+    void startDtmf(in int serial, in String s);
+
+    /**
+     * Stop playing a currently playing DTMF tone.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioVoiceResponse.stopDtmfResponse()
+     */
+    void stopDtmf(in int serial);
+
+    /**
+     * Switch waiting or holding call and active call (like AT+CHLD=2).
+     * Call transitions must happen as shown below.
+     *   BEFORE                               AFTER
+     * Call 1   Call 2                 Call 1       Call 2
+     * ACTIVE   HOLDING                HOLDING     ACTIVE
+     * ACTIVE   WAITING                HOLDING     ACTIVE
+     * HOLDING  WAITING                HOLDING     ACTIVE
+     * ACTIVE   IDLE                   HOLDING     IDLE
+     * IDLE     IDLE                   IDLE        IDLE
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioVoiceResponse.switchWaitingOrHoldingAndActiveResponse()
+     */
+    void switchWaitingOrHoldingAndActive(in int serial);
+}
diff --git a/radio/aidl/android/hardware/radio/voice/IRadioVoiceIndication.aidl b/radio/aidl/android/hardware/radio/voice/IRadioVoiceIndication.aidl
new file mode 100644
index 0000000..437fef6
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/voice/IRadioVoiceIndication.aidl
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.voice;
+
+import android.hardware.radio.RadioIndicationType;
+import android.hardware.radio.voice.CdmaCallWaiting;
+import android.hardware.radio.voice.CdmaInformationRecord;
+import android.hardware.radio.voice.CdmaOtaProvisionStatus;
+import android.hardware.radio.voice.CdmaSignalInfoRecord;
+import android.hardware.radio.voice.EmergencyNumber;
+import android.hardware.radio.voice.SrvccState;
+import android.hardware.radio.voice.StkCcUnsolSsResult;
+import android.hardware.radio.voice.UssdModeType;
+
+/**
+ * Interface declaring unsolicited radio indications for voice APIs.
+ */
+@VintfStability
+oneway interface IRadioVoiceIndication {
+    /**
+     * Ring indication for an incoming call (eg, RING or CRING event). There must be at least one
+     * callRing() at the beginning of a call and sending multiple is optional. If the system
+     * property ro.telephony.call_ring.multiple is false then the upper layers must generate the
+     * multiple events internally. Otherwise the vendor code must generate multiple callRing() if
+     * ro.telephony.call_ring.multiple is true or if it is absent.
+     * The rate of these events is controlled by ro.telephony.call_ring.delay and has a default
+     * value of 3000 (3 seconds) if absent.
+     *
+     * @param type Type of radio indication
+     * @param isGsm true for GSM & false for CDMA
+     * @param record Cdma Signal Information
+     */
+    void callRing(in RadioIndicationType type, in boolean isGsm, in CdmaSignalInfoRecord record);
+
+    /**
+     * Indicates when call state has changed. Callee must invoke IRadioVoice.getCurrentCalls().
+     * Must be invoked on, for example, "RING", "BUSY", "NO CARRIER", and also call state
+     * transitions (DIALING->ALERTING ALERTING->ACTIVE). Redundent or extraneous invocations are
+     * tolerated.
+     *
+     * @param type Type of radio indication
+     */
+    void callStateChanged(in RadioIndicationType type);
+
+    /**
+     * Indicates when CDMA radio receives a call waiting indication.
+     *
+     * @param type Type of radio indication
+     * @param callWaitingRecord Cdma CallWaiting information
+     */
+    void cdmaCallWaiting(in RadioIndicationType type, in CdmaCallWaiting callWaitingRecord);
+
+    /**
+     * Indicates when CDMA radio receives one or more info recs.
+     *
+     * @param type Type of radio indication
+     * @param records New CDMA information records.
+     *        Max length is RadioConst:CDMA_MAX_NUMBER_OF_INFO_RECS
+     */
+    void cdmaInfoRec(in RadioIndicationType type, in CdmaInformationRecord[] records);
+
+    /**
+     * Indicates when CDMA radio receives an update of the progress of an OTASP/OTAPA call.
+     *
+     * @param type Type of radio indication
+     * @param status Cdma OTA provision status
+     */
+    void cdmaOtaProvisionStatus(in RadioIndicationType type, in CdmaOtaProvisionStatus status);
+
+    /**
+     * Report the current list of emergency numbers. Each emergency number in the emergency number
+     * list contains a dialing number, zero or more service category(s), zero or more emergency
+     * uniform resource names, mobile country code, mobile network code, and source(s) that indicate
+     * where it comes from.
+     * Radio must report all the valid emergency numbers with known mobile country code, mobile
+     * network code, emergency service categories, and emergency uniform resource names from all
+     * available sources including network signaling, sim, modem/oem configuration, and default
+     * configuration (112 and 911 must be always available; additionally, 000, 08, 110, 999, 118
+     * and 119 must be available when sim is not present). Radio shall not report emergency numbers
+     * that are invalid in the current locale. The reported emergency number list must not have
+     * duplicate EmergencyNumber entries. Please refer the documentation of EmergencyNumber to
+     * construct each emergency number to report.
+     * Radio must report the complete list of emergency numbers whenever the emergency numbers in
+     * the list are changed or whenever the client and the radio server are connected.
+     *
+     * Reference: 3gpp 22.101, Section 10 - Emergency Calls;
+     *            3gpp 24.008, Section 9.2.13.4 - Emergency Number List
+     *
+     * @param type Type of radio indication
+     * @param emergencyNumberList Current list of emergency numbers known to radio.
+     */
+    void currentEmergencyNumberList(
+            in RadioIndicationType type, in EmergencyNumber[] emergencyNumberList);
+
+    /**
+     * Indicates that the radio system selection module has autonomously entered emergency
+     * callback mode.
+     *
+     * @param type Type of radio indication
+     */
+    void enterEmergencyCallbackMode(in RadioIndicationType type);
+
+    /**
+     * Indicates when Emergency Callback Mode ends. Indicates that the radio system selection module
+     * has proactively exited emergency callback mode.
+     *
+     * @param type Type of radio indication
+     */
+    void exitEmergencyCallbackMode(in RadioIndicationType type);
+
+    /**
+     * Indicates that nework doesn't have in-band information, need to play out-band tone.
+     *
+     * @param type Type of radio indication
+     * @param start true = start play ringback tone, false = stop playing ringback tone
+     */
+    void indicateRingbackTone(in RadioIndicationType type, in boolean start);
+
+    /**
+     * Indicates when Supplementary service(SS) response is received when DIAL/USSD/SS is changed to
+     * SS by call control.
+     *
+     * @param type Type of radio indication
+     */
+    void onSupplementaryServiceIndication(in RadioIndicationType type, in StkCcUnsolSsResult ss);
+
+    /**
+     * Indicates when a new USSD message is received. The USSD session is assumed to persist if the
+     * type code is REQUEST, otherwise the current session (if any) is assumed to have terminated.
+     *
+     * @param type Type of radio indication
+     * @param modeType USSD type code
+     * @param msg Message string in UTF-8, if applicable
+     */
+    void onUssd(in RadioIndicationType type, in UssdModeType modeType, in String msg);
+
+    /**
+     * Indicates that framework/application must reset the uplink mute state.
+     *
+     * @param type Type of radio indication
+     */
+    void resendIncallMute(in RadioIndicationType type);
+
+    /**
+     * Indicates when Single Radio Voice Call Continuity (SRVCC) progress state has changed.
+     *
+     * @param type Type of radio indication
+     * @param state New Srvcc State
+     */
+    void srvccStateNotify(in RadioIndicationType type, in SrvccState state);
+
+    /**
+     * Indicates when there is an ALPHA from UICC during Call Control.
+     *
+     * @param type Type of radio indication
+     * @param alpha ALPHA string from UICC in UTF-8 format
+     */
+    void stkCallControlAlphaNotify(in RadioIndicationType type, in String alpha);
+
+    /**
+     * Indicates when SIM wants application to setup a voice call.
+     *
+     * @param type Type of radio indication
+     * @param timeout Timeout value in millisec for setting up voice call
+     */
+    void stkCallSetup(in RadioIndicationType type, in long timeout);
+}
diff --git a/radio/aidl/android/hardware/radio/voice/IRadioVoiceResponse.aidl b/radio/aidl/android/hardware/radio/voice/IRadioVoiceResponse.aidl
new file mode 100644
index 0000000..cf1b953
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/voice/IRadioVoiceResponse.aidl
@@ -0,0 +1,826 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.voice;
+
+import android.hardware.radio.RadioResponseInfo;
+import android.hardware.radio.voice.Call;
+import android.hardware.radio.voice.CallForwardInfo;
+import android.hardware.radio.voice.ClipStatus;
+import android.hardware.radio.voice.LastCallFailCauseInfo;
+import android.hardware.radio.voice.TtyMode;
+
+/**
+ * Interface declaring response functions to solicited radio requests for voice APIs.
+ */
+@VintfStability
+oneway interface IRadioVoiceResponse {
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_STATE
+     *   RadioError:NO_MEMORY
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_CALL_ID
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void acceptCallResponse(in RadioResponseInfo info);
+
+    /**
+     * Acknowledge the receipt of radio request sent to the vendor. This must be sent only for
+     * radio request which take long time to respond. For more details, refer
+     * https://source.android.com/devices/tech/connect/ril.html
+     *
+     * @param serial Serial no. of the request whose acknowledgement is sent.
+     */
+    void acknowledgeRequest(in int serial);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:SIM_BUSY
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:INVALID_STATE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void cancelPendingUssdResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE (radio resetting)
+     *   RadioError:NO_MEMORY
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_STATE
+     *   RadioError:INVALID_CALL_ID
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void conferenceResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE (radio resetting)
+     *   RadioError:DIAL_MODIFIED_TO_USSD
+     *   RadioError:DIAL_MODIFIED_TO_SS
+     *   RadioError:DIAL_MODIFIED_TO_DIAL
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:NO_MEMORY
+     *   RadioError:INVALID_STATE
+     *   RadioError:NO_RESOURCES
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:FDN_CHECK_FAILURE
+     *   RadioError:MODEM_ERR
+     *   RadioError:NO_SUBSCRIPTION
+     *   RadioError:NO_NETWORK_FOUND
+     *   RadioError:INVALID_CALL_ID
+     *   RadioError:DEVICE_IN_USE
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:ABORTED
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:CANCELLED
+     */
+    void dialResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE (radio resetting)
+     *   RadioError:DIAL_MODIFIED_TO_USSD
+     *   RadioError:DIAL_MODIFIED_TO_SS
+     *   RadioError:DIAL_MODIFIED_TO_DIAL
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:NO_RESOURCES
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:FDN_CHECK_FAILURE
+     *   RadioError:MODEM_ERR
+     *   RadioError:NO_SUBSCRIPTION
+     *   RadioError:NO_NETWORK_FOUND
+     *   RadioError:INVALID_CALL_ID
+     *   RadioError:DEVICE_IN_USE
+     *   RadioError:ABORTED
+     *   RadioError:INVALID_MODEM_STATE
+     */
+    void emergencyDialResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:OPERATION_NO_ALLOWED
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:MODEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:SIM_ABSENT
+     */
+    void exitEmergencyCallbackModeResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_STATE
+     *   RadioError:NO_RESOURCES
+     *   RadioError:NO_MEMORY
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_CALL_ID
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void explicitCallTransferResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param callForwardInfos points to a vector of CallForwardInfo, one for each distinct
+     *        registered phone number. For example, if data is forwarded to +18005551212 and voice
+     *        is forwarded to +18005559999, then two separate CallForwardInfo's must be returned.
+     *        However, if both data and voice are forwarded to +18005551212, then a single
+     *        CallForwardInfo must be returned with the service class set to "data + voice = 3".
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:SS_MODIFIED_TO_DIAL
+     *   RadioError:SS_MODIFIED_TO_USSD
+     *   RadioError:SS_MODIFIED_TO_SS
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:NO_MEMORY
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:FDN_CHECK_FAILURE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void getCallForwardStatusResponse(
+            in RadioResponseInfo info, in CallForwardInfo[] callForwardInfos);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param enable If current call waiting state is disabled, enable = false else true
+     * @param serviceClass If enable, then callWaitingResp[1] must follow, with the TS 27.007
+     *        service class bit vector of services for which call waiting is enabled. For example,
+     *        if callWaitingResp[0] is 1 and callWaitingResp[1] is 3, then call waiting is enabled
+     *        for data and voice and disabled for everything else.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:SS_MODIFIED_TO_DIAL
+     *   RadioError:SS_MODIFIED_TO_USSD
+     *   RadioError:SS_MODIFIED_TO_SS
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:NO_MEMORY
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:FDN_CHECK_FAILURE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void getCallWaitingResponse(in RadioResponseInfo info, in boolean enable, in int serviceClass);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param status indicates CLIP status
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:NO_MEMORY
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:FDN_CHECK_FAILURE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void getClipResponse(in RadioResponseInfo info, in ClipStatus status);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param n is "n" parameter from TS 27.007 7.7
+     * @param m is "m" parameter from TS 27.007 7.7
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:SS_MODIFIED_TO_DIAL
+     *   RadioError:SS_MODIFIED_TO_USSD
+     *   RadioError:SS_MODIFIED_TO_SS
+     *   RadioError:NO_MEMORY
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:FDN_CHECK_FAILURE
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void getClirResponse(in RadioResponseInfo info, in int n, in int m);
+
+    /**
+     * @param info Response info struct containing respontype, serial no. and error
+     * @param calls Current call list
+     *
+     * Valid errors returned:
+     *   RadioError:NO_MEMORY
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void getCurrentCallsResponse(in RadioResponseInfo info, in Call[] calls);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param failCauseInfo Contains LastCallFailCause and vendor cause code.
+     *
+     * The vendor cause code must be used for debugging purpose only. The implementation must return
+     * one of the values of LastCallFailCause as mentioned below.
+     * GSM failure reasons codes for the cause codes defined in TS 24.008 Annex H where possible.
+     * CDMA failure reasons codes for the possible call failure scenarios described in the
+     * "CDMA IS-2000 Release A (C.S0005-A v6.0)" standard.
+     * Any of the following reason codes if the call is failed or dropped due to reason mentioned
+     * with in the braces.
+     *   LastCallFailCause:RADIO_OFF (Radio is OFF)
+     *   LastCallFailCause:OUT_OF_SERVICE (No cell coverage)
+     *   LastCallFailCause:NO_VALID_SIM (No valid SIM)
+     *   LastCallFailCause:RADIO_INTERNAL_ERROR (Modem hit unexpected error scenario)
+     *   LastCallFailCause:NETWORK_RESP_TIMEOUT (No response from network)
+     *   LastCallFailCause:NETWORK_REJECT (Explicit network reject)
+     *   LastCallFailCause:RADIO_ACCESS_FAILURE (RRC connection failure. Eg.RACH)
+     *   LastCallFailCause:RADIO_LINK_FAILURE (Radio Link Failure)
+     *   LastCallFailCause:RADIO_LINK_LOST (Radio link lost due to poor coverage)
+     *   LastCallFailCause:RADIO_UPLINK_FAILURE (Radio uplink failure)
+     *   LastCallFailCause:RADIO_SETUP_FAILURE (RRC connection setup failure)
+     *   LastCallFailCause:RADIO_RELEASE_NORMAL (RRC connection release, normal)
+     *   LastCallFailCause:RADIO_RELEASE_ABNORMAL (RRC connection release, abnormal)
+     *   LastCallFailCause:ACCESS_CLASS_BLOCKED (Access class barring)
+     *   LastCallFailCause:NETWORK_DETACH (Explicit network detach)
+     *   OEM causes (LastCallFailCause:OEM_CAUSE_XX) must be used for debug purpose only
+     *
+     * If the implementation does not have access to the exact cause codes, then it must return one
+     * of the values listed in LastCallFailCause, as the UI layer needs to distinguish these cases
+     * for tone generation or error notification.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:NO_MEMORY
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:MODEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void getLastCallFailCauseResponse(
+            in RadioResponseInfo info, in LastCallFailCauseInfo failCauseinfo);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param enable true for "mute enabled" and false for "mute disabled"
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:SS_MODIFIED_TO_DIAL
+     *   RadioError:SS_MODIFIED_TO_USSD
+     *   RadioError:SS_MODIFIED_TO_SS
+     *   RadioError:NO_MEMORY
+     *   RadioError:REQUEST_RATE_LIMITED
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void getMuteResponse(in RadioResponseInfo info, in boolean enable);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param enable false for Standard Privacy Mode (Public Long Code Mask)
+     *        true for Enhanced Privacy Mode (Private Long Code Mask)
+     *
+     * Valid errors:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void getPreferredVoicePrivacyResponse(in RadioResponseInfo info, in boolean enable);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param mode TtyMode
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void getTtyModeResponse(in RadioResponseInfo info, in TtyMode mode);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:NO_MEMORY
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:MODEM_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:SIM_ABSENT
+     */
+    void handleStkCallSetupRequestFromSimResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE (radio resetting)
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:NO_MEMORY
+     *   RadioError:INVALID_STATE
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_CALL_ID
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void hangupConnectionResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE (radio resetting)
+     *   RadioError:INVALID_STATE
+     *   RadioError:NO_MEMORY
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_CALL_ID
+     *   RadioError:NO_RESOURCES
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void hangupForegroundResumeBackgroundResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE (radio resetting)
+     *   RadioError:INVALID_STATE
+     *   RadioError:NO_MEMORY
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_CALL_ID
+     *   RadioError:NO_RESOURCES
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:CANCELLED
+     */
+    void hangupWaitingOrBackgroundResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param enable true for "vonr enabled" and false for "vonr disabled"
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void isVoNrEnabledResponse(in RadioResponseInfo info, in boolean enable);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE (radio resetting)
+     *   RadioError:INVALID_STATE
+     *   RadioError:NO_RESOURCES
+     *   RadioError:NO_MEMORY
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_CALL_ID
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void rejectCallResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:NO_MEMORY
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:MODEM_ERR
+     *   RadioError:INVALID_CALL_ID
+     *   RadioError:INVALID_STATE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:OPERATION_NOT_ALLOWED
+     */
+    void sendBurstDtmfResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:NO_MEMORY
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:MODEM_ERR
+     *   RadioError:INVALID_CALL_ID
+     *   RadioError:INVALID_STATE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     *   RadioError:OPERATION_NOT_ALLOWED
+     */
+    void sendCdmaFeatureCodeResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:NO_RESOURCES
+     *   RadioError:NO_MEMORY
+     *   RadioError:MODEM_ERR
+     *   RadioError:INVALID_CALL_ID
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:CANCELLED
+     *   RadioError:INVALID_MODEM_STATE
+     */
+    void sendDtmfResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:FDN_CHECK_FAILURE
+     *   RadioError:USSD_MODIFIED_TO_DIAL
+     *   RadioError:USSD_MODIFIED_TO_SS
+     *   RadioError:USSD_MODIFIED_TO_USSD
+     *   RadioError:SIM_BUSY
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:NO_MEMORY
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:ABORTED
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:INVALID_STATE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void sendUssdResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:INVALID_STATE
+     *   RadioError:NO_RESOURCES
+     *   RadioError:NO_MEMORY
+     *   RadioError:MODEM_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_CALL_ID
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:CANCELLED
+     */
+    void separateConnectionResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:SS_MODIFIED_TO_DIAL
+     *   RadioError:SS_MODIFIED_TO_USSD
+     *   RadioError:SS_MODIFIED_TO_SS
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:NO_MEMORY
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_STATE
+     *   RadioError:FDN_CHECK_FAILURE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void setCallForwardResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:SS_MODIFIED_TO_DIAL
+     *   RadioError:SS_MODIFIED_TO_USSD
+     *   RadioError:SS_MODIFIED_TO_SS
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:NO_MEMORY
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_STATE
+     *   RadioError:FDN_CHECK_FAILURE
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void setCallWaitingResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:SS_MODIFIED_TO_DIAL
+     *   RadioError:SS_MODIFIED_TO_USSD
+     *   RadioError:SS_MODIFIED_TO_SS
+     *   RadioError:NO_MEMORY
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void setClirResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:NO_MEMORY
+     *   RadioError:REQUEST_RATE_LIMITED
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void setMuteResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:INVALID_CALL_ID
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void setPreferredVoicePrivacyResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void setTtyModeResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    void setVoNrEnabledResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:NO_RESOURCES
+     *   RadioError:NO_MEMORY
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_CALL_ID
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:CANCELLED
+     *   RadioError:INVALID_MODEM_STATE
+     */
+    void startDtmfResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:NO_RESOURCES
+     *   RadioError:NO_MEMORY
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_CALL_ID
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:CANCELLED
+     *   RadioError:INVALID_MODEM_STATE
+     */
+    void stopDtmfResponse(in RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE (radio resetting)
+     *   RadioError:INVALID_STATE
+     *   RadioError:NO_MEMORY
+     *   RadioError:MODEM_ERR
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_STATE
+     *   RadioError:INVALID_CALL_ID
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    void switchWaitingOrHoldingAndActiveResponse(in RadioResponseInfo info);
+}
diff --git a/radio/aidl/android/hardware/radio/voice/LastCallFailCause.aidl b/radio/aidl/android/hardware/radio/voice/LastCallFailCause.aidl
new file mode 100644
index 0000000..5c8c819
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/voice/LastCallFailCause.aidl
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.voice;
+
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum LastCallFailCause {
+    UNOBTAINABLE_NUMBER = 1,
+    NO_ROUTE_TO_DESTINATION = 3,
+    CHANNEL_UNACCEPTABLE = 6,
+    OPERATOR_DETERMINED_BARRING = 8,
+    NORMAL = 16,
+    BUSY = 17,
+    NO_USER_RESPONDING = 18,
+    NO_ANSWER_FROM_USER = 19,
+    CALL_REJECTED = 21,
+    NUMBER_CHANGED = 22,
+    PREEMPTION = 25,
+    DESTINATION_OUT_OF_ORDER = 27,
+    INVALID_NUMBER_FORMAT = 28,
+    FACILITY_REJECTED = 29,
+    RESP_TO_STATUS_ENQUIRY = 30,
+    NORMAL_UNSPECIFIED = 31,
+    CONGESTION = 34,
+    NETWORK_OUT_OF_ORDER = 38,
+    TEMPORARY_FAILURE = 41,
+    SWITCHING_EQUIPMENT_CONGESTION = 42,
+    ACCESS_INFORMATION_DISCARDED = 43,
+    REQUESTED_CIRCUIT_OR_CHANNEL_NOT_AVAILABLE = 44,
+    RESOURCES_UNAVAILABLE_OR_UNSPECIFIED = 47,
+    QOS_UNAVAILABLE = 49,
+    REQUESTED_FACILITY_NOT_SUBSCRIBED = 50,
+    INCOMING_CALLS_BARRED_WITHIN_CUG = 55,
+    BEARER_CAPABILITY_NOT_AUTHORIZED = 57,
+    BEARER_CAPABILITY_UNAVAILABLE = 58,
+    SERVICE_OPTION_NOT_AVAILABLE = 63,
+    BEARER_SERVICE_NOT_IMPLEMENTED = 65,
+    ACM_LIMIT_EXCEEDED = 68,
+    REQUESTED_FACILITY_NOT_IMPLEMENTED = 69,
+    ONLY_DIGITAL_INFORMATION_BEARER_AVAILABLE = 70,
+    SERVICE_OR_OPTION_NOT_IMPLEMENTED = 79,
+    INVALID_TRANSACTION_IDENTIFIER = 81,
+    USER_NOT_MEMBER_OF_CUG = 87,
+    INCOMPATIBLE_DESTINATION = 88,
+    INVALID_TRANSIT_NW_SELECTION = 91,
+    SEMANTICALLY_INCORRECT_MESSAGE = 95,
+    INVALID_MANDATORY_INFORMATION = 96,
+    MESSAGE_TYPE_NON_IMPLEMENTED = 97,
+    MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 98,
+    INFORMATION_ELEMENT_NON_EXISTENT = 99,
+    CONDITIONAL_IE_ERROR = 100,
+    MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 101,
+    RECOVERY_ON_TIMER_EXPIRED = 102,
+    PROTOCOL_ERROR_UNSPECIFIED = 111,
+    INTERWORKING_UNSPECIFIED = 127,
+    CALL_BARRED = 240,
+    FDN_BLOCKED = 241,
+    IMSI_UNKNOWN_IN_VLR = 242,
+    IMEI_NOT_ACCEPTED = 243,
+    /**
+     * STK Call Control
+     */
+    DIAL_MODIFIED_TO_USSD = 244,
+    DIAL_MODIFIED_TO_SS = 245,
+    DIAL_MODIFIED_TO_DIAL = 246,
+    /**
+     * Radio is off
+     */
+    RADIO_OFF = 247,
+    /**
+     * No cellular coverage
+     */
+    OUT_OF_SERVICE = 248,
+    /**
+     * No valid SIM is present
+     */
+    NO_VALID_SIM = 249,
+    /**
+     * Internal error at modem
+     */
+    RADIO_INTERNAL_ERROR = 250,
+    /**
+     * No response from network
+     */
+    NETWORK_RESP_TIMEOUT = 251,
+    /**
+     * Explicit network reject
+     */
+    NETWORK_REJECT = 252,
+    /**
+     * RRC connection failure. Eg.RACH
+     */
+    RADIO_ACCESS_FAILURE = 253,
+    /**
+     * Radio link failure
+     */
+    RADIO_LINK_FAILURE = 254,
+    /**
+     * Radio link lost due to poor coverage
+     */
+    RADIO_LINK_LOST = 255,
+    /**
+     * Radio uplink failure
+     */
+    RADIO_UPLINK_FAILURE = 256,
+    /**
+     * RRC connection setup failure
+     */
+    RADIO_SETUP_FAILURE = 257,
+    /**
+     * RRC connection release, normal
+     */
+    RADIO_RELEASE_NORMAL = 258,
+    /**
+     * RRC connection release, abnormal
+     */
+    RADIO_RELEASE_ABNORMAL = 259,
+    /**
+     * Access class barring
+     */
+    ACCESS_CLASS_BLOCKED = 260,
+    /**
+     * Explicit network detach
+     */
+    NETWORK_DETACH = 261,
+    CDMA_LOCKED_UNTIL_POWER_CYCLE = 1000,
+    CDMA_DROP = 1001,
+    CDMA_INTERCEPT = 1002,
+    CDMA_REORDER = 1003,
+    CDMA_SO_REJECT = 1004,
+    CDMA_RETRY_ORDER = 1005,
+    CDMA_ACCESS_FAILURE = 1006,
+    CDMA_PREEMPTED = 1007,
+    /**
+     * For non-emergency number dialed during emergency callback mode
+     */
+    CDMA_NOT_EMERGENCY = 1008,
+    CDMA_ACCESS_BLOCKED = 1009,
+    /**
+     * OEM specific error codes. Used to distinguish error from
+     * CALL_FAIL_ERROR_UNSPECIFIED and help assist debugging
+     */
+    OEM_CAUSE_1 = 0xf001,
+    OEM_CAUSE_2 = 0xf002,
+    OEM_CAUSE_3 = 0xf003,
+    OEM_CAUSE_4 = 0xf004,
+    OEM_CAUSE_5 = 0xf005,
+    OEM_CAUSE_6 = 0xf006,
+    OEM_CAUSE_7 = 0xf007,
+    OEM_CAUSE_8 = 0xf008,
+    OEM_CAUSE_9 = 0xf009,
+    OEM_CAUSE_10 = 0xf00a,
+    OEM_CAUSE_11 = 0xf00b,
+    OEM_CAUSE_12 = 0xf00c,
+    OEM_CAUSE_13 = 0xf00d,
+    OEM_CAUSE_14 = 0xf00e,
+    OEM_CAUSE_15 = 0xf00f,
+    /**
+     * This error will be deprecated soon, vendor code must make sure to map error code to specific
+     * error
+     */
+    ERROR_UNSPECIFIED = 0xffff,
+}
diff --git a/radio/aidl/android/hardware/radio/voice/LastCallFailCauseInfo.aidl b/radio/aidl/android/hardware/radio/voice/LastCallFailCauseInfo.aidl
new file mode 100644
index 0000000..078722a
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/voice/LastCallFailCauseInfo.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.voice;
+
+import android.hardware.radio.voice.LastCallFailCause;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable LastCallFailCauseInfo {
+    LastCallFailCause causeCode;
+    String vendorCause;
+}
diff --git a/radio/aidl/android/hardware/radio/voice/SrvccState.aidl b/radio/aidl/android/hardware/radio/voice/SrvccState.aidl
new file mode 100644
index 0000000..08eb877
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/voice/SrvccState.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.voice;
+
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum SrvccState {
+    HANDOVER_STARTED,
+    HANDOVER_COMPLETED,
+    HANDOVER_FAILED,
+    HANDOVER_CANCELED,
+}
diff --git a/radio/aidl/android/hardware/radio/voice/SsInfoData.aidl b/radio/aidl/android/hardware/radio/voice/SsInfoData.aidl
new file mode 100644
index 0000000..b944bf4
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/voice/SsInfoData.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.voice;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable SsInfoData {
+    const int SS_INFO_MAX = 4;
+    /**
+     * This is the response data for all of the SS GET/SET Radio requests.
+     * E.g. IRadioVoice.getClir() returns two ints, so first two values of ssInfo[] will be used for
+     * response if serviceType is SS_CLIR and requestType is SS_INTERROGATION.
+     * Max size = SS_INFO_MAX
+     */
+    int[] ssInfo;
+}
diff --git a/radio/aidl/android/hardware/radio/voice/StkCcUnsolSsResult.aidl b/radio/aidl/android/hardware/radio/voice/StkCcUnsolSsResult.aidl
new file mode 100644
index 0000000..7982275
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/voice/StkCcUnsolSsResult.aidl
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.voice;
+
+import android.hardware.radio.RadioError;
+import android.hardware.radio.voice.CfData;
+import android.hardware.radio.voice.SsInfoData;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable StkCcUnsolSsResult {
+    const int REQUEST_TYPE_ACTIVATION = 0;
+    const int REQUEST_TYPE_DEACTIVATION = 1;
+    const int REQUEST_TYPE_INTERROGATION = 2;
+    const int REQUEST_TYPE_REGISTRATION = 3;
+    const int REQUEST_TYPE_ERASURE = 4;
+
+    const int SERVICE_TYPE_CFU = 0;
+    const int SERVICE_TYPE_CF_BUSY = 1;
+    const int SERVICE_TYPE_CF_NO_REPLY = 2;
+    const int SERVICE_TYPE_CF_NOT_REACHABLE = 3;
+    const int SERVICE_TYPE_CF_ALL = 4;
+    const int SERVICE_TYPE_CF_ALL_CONDITIONAL = 5;
+    const int SERVICE_TYPE_CLIP = 6;
+    const int SERVICE_TYPE_CLIR = 7;
+    const int SERVICE_TYPE_COLP = 8;
+    const int SERVICE_TYPE_COLR = 9;
+    const int SERVICE_TYPE_WAIT = 10;
+    const int SERVICE_TYPE_BAOC = 11;
+    const int SERVICE_TYPE_BAOIC = 12;
+    const int SERVICE_TYPE_BAOIC_EXC_HOME = 13;
+    const int SERVICE_TYPE_BAIC = 14;
+    const int SERVICE_TYPE_BAIC_ROAMING = 15;
+    const int SERVICE_TYPE_ALL_BARRING = 16;
+    const int SERVICE_TYPE_OUTGOING_BARRING = 17;
+    const int SERVICE_TYPE_INCOMING_BARRING = 18;
+
+    const int TELESERVICE_TYPE_ALL_TELE_AND_BEARER_SERVICES = 0;
+    const int TELESERVICE_TYPE_ALL_TELESEVICES = 1;
+    const int TELESERVICE_TYPE_TELEPHONY = 2;
+    const int TELESERVICE_TYPE_ALL_DATA_TELESERVICES = 3;
+    const int TELESERVICE_TYPE_SMS_SERVICES = 4;
+    const int TELESERVICE_TYPE_ALL_TELESERVICES_EXCEPT_SMS = 5;
+
+    const int SUPP_SERVICE_CLASS_NONE = 0;
+    const int SUPP_SERVICE_CLASS_VOICE = 1 << 0;
+    const int SUPP_SERVICE_CLASS_DATA = 1 << 1;
+    const int SUPP_SERVICE_CLASS_FAX = 1 << 2;
+    const int SUPP_SERVICE_CLASS_SMS = 1 << 3;
+    const int SUPP_SERVICE_CLASS_DATA_SYNC = 1 << 4;
+    const int SUPP_SERVICE_CLASS_DATA_ASYNC = 1 << 5;
+    const int SUPP_SERVICE_CLASS_PACKET = 1 << 6;
+    const int SUPP_SERVICE_CLASS_PAD = 1 << 7;
+    const int SUPP_SERVICE_CLASS_MAX = 1 << 7;
+
+    /**
+     * Values are SERVICE_TYPE_
+     */
+    int serviceType;
+    /**
+     * Values are REQUEST_TYPE_
+     */
+    int requestType;
+    /**
+     * Values are TELESERVICE_TYPE_
+     */
+    int teleserviceType;
+    /**
+     * Values are a bitfield of SUPP_SERVICE_CLASS_
+     */
+    int serviceClass;
+    RadioError result;
+    /**
+     * Valid only for all serviceType except SERVICE_TYPE_CF_* else empty.
+     * Only one of ssInfo and cfData may contain values and the other must be empty.
+     */
+    SsInfoData[] ssInfo;
+    /**
+     * Valid for serviceType SERVICE_TYPE_CF_* else empty
+     * Only one of ssInfo and cfData may contain values and the other must be empty.
+     */
+    CfData[] cfData;
+}
diff --git a/radio/aidl/android/hardware/radio/voice/TtyMode.aidl b/radio/aidl/android/hardware/radio/voice/TtyMode.aidl
new file mode 100644
index 0000000..e8dd723
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/voice/TtyMode.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.voice;
+
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum TtyMode {
+    OFF,
+    FULL,
+    /**
+     * Hearing carryover
+     */
+    HCO,
+    /**
+     * Voice carryover
+     */
+    VCO,
+}
diff --git a/radio/aidl/android/hardware/radio/voice/UssdModeType.aidl b/radio/aidl/android/hardware/radio/voice/UssdModeType.aidl
new file mode 100644
index 0000000..cece4bd
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/voice/UssdModeType.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.voice;
+
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum UssdModeType {
+    /**
+     * USSD-Notify
+     */
+    NOTIFY,
+    /**
+     * USSD-Request
+     */
+    REQUEST,
+    /**
+     * Session terminated by network
+     */
+    NW_RELEASE,
+    /**
+     * Other local client (eg, SIM Toolkit) has responded
+     */
+    LOCAL_CLIENT,
+    /**
+     * Operation not supported
+     */
+    NOT_SUPPORTED,
+    /**
+     * Network timeout
+     */
+    NW_TIMEOUT,
+}
diff --git a/radio/aidl/android/hardware/radio/voice/UusInfo.aidl b/radio/aidl/android/hardware/radio/voice/UusInfo.aidl
new file mode 100644
index 0000000..220a8fc
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/voice/UusInfo.aidl
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.voice;
+
+/**
+ * User-to-User Signaling Information defined in 3GPP 23.087 v8.0
+ */
+@VintfStability
+@JavaDerive(toString=true)
+parcelable UusInfo {
+    /**
+     * User specified protocol
+     */
+    const int UUS_DCS_USP = 0;
+    /**
+     * OSI higher layer protocol
+     */
+    const int UUS_DCS_OSIHLP = 1;
+    /**
+     * X.244
+     */
+    const int UUS_DCS_X244 = 2;
+    /**
+     * Reserved for system management
+     */
+    const int UUS_DCS_RMCF = 3;
+    /**
+     * IA5 characters
+     */
+    const int UUS_DCS_IA5C = 4;
+
+    const int UUS_TYPE_TYPE1_IMPLICIT = 0;
+    const int UUS_TYPE_TYPE1_REQUIRED = 1;
+    const int UUS_TYPE_TYPE1_NOT_REQUIRED = 2;
+    const int UUS_TYPE_TYPE2_REQUIRED = 3;
+    const int UUS_TYPE_TYPE2_NOT_REQUIRED = 4;
+    const int UUS_TYPE_TYPE3_REQUIRED = 5;
+    const int UUS_TYPE_TYPE3_NOT_REQUIRED = 6;
+
+    /**
+     * User-to-User Signaling Information activation types derived from 3GPP 23.087 v8.0
+     * Values are UUS_TYPE_
+     */
+    int uusType;
+    /**
+     * User-to-User Signaling Information data coding schemes. Possible values for Octet 3 (Protocol
+     * Discriminator field) in the UUIE. The values have been specified in section 10.5.4.25 of
+     * 3GPP TS 24.008
+     * Values are UUS_DCS_
+     */
+    int uusDcs;
+    /**
+     * UUS data
+     */
+    String uusData;
+}
diff --git a/radio/aidl/compat/OWNERS b/radio/aidl/compat/OWNERS
new file mode 100644
index 0000000..471d806
--- /dev/null
+++ b/radio/aidl/compat/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 20868
+include ../../1.0/vts/OWNERS
+twasilczyk@google.com
diff --git a/radio/aidl/compat/libradiocompat/Android.bp b/radio/aidl/compat/libradiocompat/Android.bp
new file mode 100644
index 0000000..487d91b
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/Android.bp
@@ -0,0 +1,95 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+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.radio-library.compat",
+    relative_install_path: "hw",
+    vendor: true,
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
+    ],
+    shared_libs: [
+        "android.hardware.radio.config-V1-ndk",
+        "android.hardware.radio.config@1.0",
+        "android.hardware.radio.config@1.1",
+        "android.hardware.radio.config@1.2",
+        "android.hardware.radio.config@1.3",
+        "android.hardware.radio.data-V1-ndk",
+        "android.hardware.radio.messaging-V1-ndk",
+        "android.hardware.radio.modem-V1-ndk",
+        "android.hardware.radio.network-V1-ndk",
+        "android.hardware.radio.sim-V1-ndk",
+        "android.hardware.radio.voice-V1-ndk",
+        "android.hardware.radio@1.0",
+        "android.hardware.radio@1.1",
+        "android.hardware.radio@1.2",
+        "android.hardware.radio@1.3",
+        "android.hardware.radio@1.4",
+        "android.hardware.radio@1.5",
+        "android.hardware.radio@1.6",
+        "libbase",
+        "libbinder_ndk",
+        "libhidlbase",
+        "libutils",
+    ],
+    srcs: [
+        "CallbackManager.cpp",
+        "DriverContext.cpp",
+        "RadioCompatBase.cpp",
+        "RadioIndication.cpp",
+        "RadioResponse.cpp",
+        "commonStructs.cpp",
+        "config/RadioConfig.cpp",
+        "config/RadioConfigIndication.cpp",
+        "config/RadioConfigResponse.cpp",
+        "config/structs.cpp",
+        "data/RadioIndication-data.cpp",
+        "data/RadioResponse-data.cpp",
+        "data/RadioData.cpp",
+        "data/structs.cpp",
+        "messaging/RadioIndication-messaging.cpp",
+        "messaging/RadioMessaging.cpp",
+        "messaging/RadioResponse-messaging.cpp",
+        "messaging/structs.cpp",
+        "modem/RadioIndication-modem.cpp",
+        "modem/RadioResponse-modem.cpp",
+        "modem/RadioModem.cpp",
+        "modem/structs.cpp",
+        "network/RadioIndication-network.cpp",
+        "network/RadioNetwork.cpp",
+        "network/RadioResponse-network.cpp",
+        "network/structs.cpp",
+        "network/utils.cpp",
+        "sim/RadioIndication-sim.cpp",
+        "sim/RadioResponse-sim.cpp",
+        "sim/RadioSim.cpp",
+        "sim/structs.cpp",
+        "voice/RadioIndication-voice.cpp",
+        "voice/RadioResponse-voice.cpp",
+        "voice/RadioVoice.cpp",
+        "voice/structs.cpp",
+    ],
+    export_include_dirs: ["include"],
+}
diff --git a/radio/aidl/compat/libradiocompat/CallbackManager.cpp b/radio/aidl/compat/libradiocompat/CallbackManager.cpp
new file mode 100644
index 0000000..c2eaed1
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/CallbackManager.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libradiocompat/CallbackManager.h>
+
+#include <android-base/logging.h>
+
+using namespace std::literals::chrono_literals;
+
+namespace android::hardware::radio::compat {
+
+/**
+ * How much setter thread will wait with setting response functions after the last
+ * setResponseFunctions call from the framework. Subsequent calls from the framework reset the
+ * clock, so this number should be larger than the longest time between setResponseFunctions calls
+ * from the framework.
+ *
+ * Real world measurements with Cuttlefish give <10ms delay between Modem and Data and <2ms delays
+ * between all others.
+ */
+static constexpr auto kDelayedSetterDelay = 100ms;
+
+CallbackManager::CallbackManager(std::shared_ptr<DriverContext> context, sp<V1_5::IRadio> hidlHal)
+    : mHidlHal(hidlHal),
+      mRadioResponse(sp<compat::RadioResponse>::make(context)),
+      mRadioIndication(sp<compat::RadioIndication>::make(context)),
+      mDelayedSetterThread(&CallbackManager::delayedSetterThread, this) {}
+
+CallbackManager::~CallbackManager() {
+    {
+        std::unique_lock<std::mutex> lock(mDelayedSetterGuard);
+        mDelayedSetterDeadline = std::nullopt;
+        mDestroy = true;
+        mDelayedSetterCv.notify_all();
+    }
+    mDelayedSetterThread.join();
+}
+
+RadioResponse& CallbackManager::response() const {
+    return *mRadioResponse;
+}
+
+void CallbackManager::setResponseFunctionsDelayed() {
+    std::unique_lock<std::mutex> lock(mDelayedSetterGuard);
+    mDelayedSetterDeadline = std::chrono::steady_clock::now() + kDelayedSetterDelay;
+    mDelayedSetterCv.notify_all();
+}
+
+void CallbackManager::delayedSetterThread() {
+    while (!mDestroy) {
+        std::unique_lock<std::mutex> lock(mDelayedSetterGuard);
+        auto deadline = mDelayedSetterDeadline;
+
+        // not waiting to set response functions
+        if (!deadline) {
+            mDelayedSetterCv.wait(lock);
+            continue;
+        }
+
+        // waiting to set response functions, but not yet
+        if (*deadline > std::chrono::steady_clock::now()) {
+            mDelayedSetterCv.wait_until(lock, *deadline);
+            continue;
+        }
+
+        mHidlHal->setResponseFunctions(mRadioResponse, mRadioIndication).assertOk();
+        mDelayedSetterDeadline = std::nullopt;
+    }
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/DriverContext.cpp b/radio/aidl/compat/libradiocompat/DriverContext.cpp
new file mode 100644
index 0000000..a07173e
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/DriverContext.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libradiocompat/DriverContext.h>
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio;
+
+void DriverContext::addDataProfile(const aidl::data::DataProfileInfo& profile) {
+    mDataProfiles[profile.apn] = profile;
+}
+
+aidl::data::DataProfileInfo DriverContext::getDataProfile(const std::string& apn) {
+    const auto it = mDataProfiles.find(apn);
+    if (it != mDataProfiles.end()) return it->second;
+
+    // if not found in cache, return a made up default
+    return {
+            .apn = apn,
+    };
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/RadioCompatBase.cpp b/radio/aidl/compat/libradiocompat/RadioCompatBase.cpp
new file mode 100644
index 0000000..2a2d7a3
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/RadioCompatBase.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libradiocompat/RadioCompatBase.h>
+
+#include <android-base/logging.h>
+
+namespace android::hardware::radio::compat {
+
+RadioCompatBase::RadioCompatBase(std::shared_ptr<DriverContext> context, sp<V1_5::IRadio> hidlHal,
+                                 std::shared_ptr<CallbackManager> cbMgr)
+    : mContext(context),
+      mHal1_5(hidlHal),
+      mHal1_6(V1_6::IRadio::castFrom(hidlHal)),
+      mCallbackManager(cbMgr) {}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/RadioIndication.cpp b/radio/aidl/compat/libradiocompat/RadioIndication.cpp
new file mode 100644
index 0000000..30ef6a0
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/RadioIndication.cpp
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libradiocompat/RadioIndication.h>
+
+namespace android::hardware::radio::compat {
+
+RadioIndication::RadioIndication(std::shared_ptr<DriverContext> context) : mContext(context) {}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/RadioResponse.cpp b/radio/aidl/compat/libradiocompat/RadioResponse.cpp
new file mode 100644
index 0000000..dab70cc
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/RadioResponse.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libradiocompat/RadioResponse.h>
+
+#include "debug.h"
+
+#define RADIO_MODULE "Common"
+
+namespace android::hardware::radio::compat {
+
+RadioResponse::RadioResponse(std::shared_ptr<DriverContext> context) : mContext(context) {}
+
+Return<void> RadioResponse::acknowledgeRequest(int32_t serial) {
+    LOG_CALL << serial;
+    /* We send ACKs to all callbacks instead of the one requested it to make implementation simpler.
+     * If it turns out to be a problem, we would have to track where serials come from and make sure
+     * this tracking data (e.g. a map) doesn't grow indefinitely.
+     */
+    if (mDataCb) mDataCb.get()->acknowledgeRequest(serial);
+    if (mMessagingCb) mMessagingCb.get()->acknowledgeRequest(serial);
+    if (mModemCb) mModemCb.get()->acknowledgeRequest(serial);
+    if (mNetworkCb) mNetworkCb.get()->acknowledgeRequest(serial);
+    if (mSimCb) mSimCb.get()->acknowledgeRequest(serial);
+    if (mVoiceCb) mVoiceCb.get()->acknowledgeRequest(serial);
+    return {};
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/collections.h b/radio/aidl/compat/libradiocompat/collections.h
new file mode 100644
index 0000000..082ef17
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/collections.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <hidl/HidlSupport.h>
+
+#include <type_traits>
+#include <variant>
+
+namespace android::hardware::radio::compat {
+
+/**
+ * Converts hidl_vec<T> HIDL list to std::vector<T> AIDL list.
+ *
+ * To convert values, the template uses toAidl functions for a given type T, assuming it's defined.
+ *
+ * \param inp vector to convert
+ */
+template <typename T>
+auto toAidl(const hidl_vec<T>& inp) {
+    std::vector<decltype(toAidl(T{}))> out(inp.size());
+    for (size_t i = 0; i < inp.size(); i++) {
+        out[i] = toAidl(inp[i]);
+    }
+    return out;
+}
+
+/**
+ * Converts std::vector<T> AIDL list to hidl_vec<T> HIDL list.
+ *
+ * To convert values, the template uses toHidl functions for a given type T, assuming it's defined.
+ *
+ * \param inp vector to convert
+ */
+template <typename T>
+auto toHidl(const std::vector<T>& inp) {
+    hidl_vec<decltype(toHidl(T{}))> out(inp.size());
+    for (size_t i = 0; i < inp.size(); i++) {
+        out[i] = toHidl(inp[i]);
+    }
+    return out;
+}
+
+/**
+ * Converts hidl_array<T> HIDL list to std::vector<T> AIDL list.
+ *
+ * To convert values, the template uses toAidl functions for a given type T, assuming it's defined.
+ *
+ * \param inp array to convert
+ */
+template <typename T, size_t N>
+auto toAidl(const hidl_array<T, N>& inp) {
+    std::vector<decltype(toAidl(T{}))> out(N);
+    for (size_t i = 0; i < N; i++) {
+        out[i] = toAidl(inp[i]);
+    }
+    return out;
+}
+
+/**
+ * Converts T=OptionalX HIDL value to std::optional<X> AIDL value.
+ *
+ * To convert values, the template uses toAidl functions for a given type T.value.
+ */
+template <typename T>
+std::optional<decltype(toAidl(T{}.value()))> toAidl(const T& opt) {
+    if (opt.getDiscriminator() == T::hidl_discriminator::noinit) return std::nullopt;
+    return toAidl(opt.value());
+}
+
+/**
+ * Converts T=OptionalX HIDL value to std::variant<bool, X> AIDL value.
+ *
+ * For some reason, not every OptionalX gets generated into a std::optional<X>.
+ */
+template <typename T>
+std::variant<bool, decltype(toAidl(T{}.value()))> toAidlVariant(const T& opt) {
+    if (opt.getDiscriminator() == T::hidl_discriminator::noinit) return false;
+    return toAidl(opt.value());
+}
+
+/**
+ * Converts std::optional<X> AIDL value to T=OptionalX HIDL value.
+ *
+ * X is inferred from toAidl(T.value) declaration. Please note that toAidl(T.value) doesn't have to
+ * be implemented if it's not needed for anything else than giving this hint to type system.
+ *
+ * To convert values, the template uses toHidl functions for a given type T, assuming it's defined.
+ *
+ * \param opt value to convert
+ */
+template <typename T>
+T toHidl(const std::optional<decltype(toAidl(T{}.value()))>& opt) {
+    T hidl;
+    if (opt.has_value()) hidl.value(toHidl(*opt));
+    return hidl;
+}
+
+/**
+ * Converts U AIDL bitfield value to HIDL T bitfield value.
+ *
+ * \param val value to convert
+ */
+template <typename T, typename U>
+hidl_bitfield<T> toHidlBitfield(U val) {
+    return static_cast<int>(val);
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/commonStructs.cpp b/radio/aidl/compat/libradiocompat/commonStructs.cpp
new file mode 100644
index 0000000..6e4c873
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/commonStructs.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "commonStructs.h"
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio;
+
+aidl::RadioResponseInfo notSupported(int32_t serial) {
+    return {
+            .type = aidl::RadioResponseType::SOLICITED,
+            .serial = serial,
+            .error = aidl::RadioError::REQUEST_NOT_SUPPORTED,
+    };
+}
+
+std::string toAidl(const hidl_string& str) {
+    return str;
+}
+
+hidl_string toHidl(const std::string& str) {
+    return str;
+}
+
+uint8_t toAidl(int8_t v) {
+    return v;
+}
+
+int8_t toAidl(uint8_t v) {
+    return v;
+}
+
+int32_t toAidl(uint32_t v) {
+    return v;
+}
+
+aidl::RadioIndicationType toAidl(V1_0::RadioIndicationType type) {
+    return aidl::RadioIndicationType(type);
+}
+
+aidl::RadioResponseType toAidl(V1_0::RadioResponseType type) {
+    return aidl::RadioResponseType(type);
+}
+
+aidl::RadioError toAidl(V1_0::RadioError err) {
+    return aidl::RadioError(err);
+}
+
+aidl::RadioError toAidl(V1_6::RadioError err) {
+    return aidl::RadioError(err);
+}
+
+aidl::RadioResponseInfo toAidl(const V1_0::RadioResponseInfo& info) {
+    return {
+            .type = toAidl(info.type),
+            .serial = info.serial,
+            .error = toAidl(info.error),
+    };
+}
+
+aidl::RadioResponseInfo toAidl(const V1_6::RadioResponseInfo& info) {
+    return {
+            .type = toAidl(info.type),
+            .serial = info.serial,
+            .error = toAidl(info.error),
+    };
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/commonStructs.h b/radio/aidl/compat/libradiocompat/commonStructs.h
new file mode 100644
index 0000000..a4a4869
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/commonStructs.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <aidl/android/hardware/radio/RadioIndicationType.h>
+#include <aidl/android/hardware/radio/RadioResponseInfo.h>
+#include <android/hardware/radio/1.6/types.h>
+
+namespace android::hardware::radio::compat {
+
+aidl::android::hardware::radio::RadioResponseInfo notSupported(int32_t serial);
+
+std::string toAidl(const hidl_string& str);
+hidl_string toHidl(const std::string& str);
+uint8_t toAidl(int8_t v);
+int8_t toAidl(uint8_t v);
+int32_t toAidl(uint32_t v);
+
+aidl::android::hardware::radio::RadioIndicationType toAidl(V1_0::RadioIndicationType type);
+aidl::android::hardware::radio::RadioResponseType toAidl(V1_0::RadioResponseType type);
+aidl::android::hardware::radio::RadioError toAidl(V1_0::RadioError type);
+aidl::android::hardware::radio::RadioError toAidl(V1_6::RadioError type);
+
+aidl::android::hardware::radio::RadioResponseInfo toAidl(const V1_0::RadioResponseInfo& info);
+aidl::android::hardware::radio::RadioResponseInfo toAidl(const V1_6::RadioResponseInfo& info);
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/config/RadioConfig.cpp b/radio/aidl/compat/libradiocompat/config/RadioConfig.cpp
new file mode 100644
index 0000000..b450418
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/config/RadioConfig.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libradiocompat/RadioConfig.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "Config"
+
+namespace android::hardware::radio::compat {
+
+using ::ndk::ScopedAStatus;
+namespace aidl = ::aidl::android::hardware::radio::config;
+constexpr auto ok = &ScopedAStatus::ok;
+
+RadioConfig::RadioConfig(sp<config::V1_1::IRadioConfig> hidlHal)
+    : mHal1_1(hidlHal),
+      mHal1_3(config::V1_3::IRadioConfig::castFrom(hidlHal)),
+      mRadioConfigResponse(sp<RadioConfigResponse>::make()),
+      mRadioConfigIndication(sp<RadioConfigIndication>::make()) {}
+
+std::shared_ptr<aidl::IRadioConfigResponse> RadioConfig::respond() {
+    return mRadioConfigResponse->respond();
+}
+
+ScopedAStatus RadioConfig::getHalDeviceCapabilities(int32_t serial) {
+    LOG_CALL << serial;
+    if (mHal1_3) {
+        mHal1_3->getHalDeviceCapabilities(serial);
+    } else {
+        respond()->getHalDeviceCapabilitiesResponse(notSupported(serial), false);
+    }
+    return ok();
+}
+
+ScopedAStatus RadioConfig::getNumOfLiveModems(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_1->getModemsConfig(serial);
+    return ok();
+}
+
+ScopedAStatus RadioConfig::getPhoneCapability(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_1->getPhoneCapability(serial);
+    return ok();
+}
+
+ScopedAStatus RadioConfig::getSimSlotsStatus(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_1->getSimSlotsStatus(serial);
+    return ok();
+}
+
+ScopedAStatus RadioConfig::setNumOfLiveModems(int32_t serial, int8_t numOfLiveModems) {
+    LOG_CALL << serial;
+    mHal1_1->setModemsConfig(serial, {static_cast<uint8_t>(numOfLiveModems)});
+    return ok();
+}
+
+ScopedAStatus RadioConfig::setPreferredDataModem(int32_t serial, int8_t modemId) {
+    LOG_CALL << serial;
+    mHal1_1->setPreferredDataModem(serial, modemId);
+    return ok();
+}
+
+ScopedAStatus RadioConfig::setResponseFunctions(
+        const std::shared_ptr<aidl::IRadioConfigResponse>& radioConfigResponse,
+        const std::shared_ptr<aidl::IRadioConfigIndication>& radioConfigIndication) {
+    LOG_CALL << radioConfigResponse << ' ' << radioConfigIndication;
+
+    CHECK(radioConfigResponse);
+    CHECK(radioConfigIndication);
+
+    mRadioConfigResponse->setResponseFunction(radioConfigResponse);
+    mRadioConfigIndication->setResponseFunction(radioConfigIndication);
+    mHal1_1->setResponseFunctions(mRadioConfigResponse, mRadioConfigIndication).assertOk();
+
+    return ok();
+}
+
+ScopedAStatus RadioConfig::setSimSlotsMapping(  //
+        int32_t serial, const std::vector<aidl::SlotPortMapping>& slotMap) {
+    LOG_CALL << serial;
+    mHal1_1->setSimSlotsMapping(serial, toHidl(slotMap));
+    return ok();
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/config/RadioConfigIndication.cpp b/radio/aidl/compat/libradiocompat/config/RadioConfigIndication.cpp
new file mode 100644
index 0000000..c1e32c1
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/config/RadioConfigIndication.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libradiocompat/RadioConfigIndication.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "ConfigIndication"
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::config;
+
+void RadioConfigIndication::setResponseFunction(
+        std::shared_ptr<aidl::IRadioConfigIndication> callback) {
+    mCallback = callback;
+}
+
+std::shared_ptr<aidl::IRadioConfigIndication> RadioConfigIndication::indicate() {
+    return mCallback.get();
+}
+
+Return<void> RadioConfigIndication::simSlotsStatusChanged(
+        V1_0::RadioIndicationType type, const hidl_vec<config::V1_0::SimSlotStatus>& slotStatus) {
+    LOG_CALL << type;
+    indicate()->simSlotsStatusChanged(toAidl(type), toAidl(slotStatus));
+    return {};
+}
+
+Return<void> RadioConfigIndication::simSlotsStatusChanged_1_2(
+        V1_0::RadioIndicationType type, const hidl_vec<config::V1_2::SimSlotStatus>& slotStatus) {
+    LOG_CALL << type;
+    indicate()->simSlotsStatusChanged(toAidl(type), toAidl(slotStatus));
+    return {};
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/config/RadioConfigResponse.cpp b/radio/aidl/compat/libradiocompat/config/RadioConfigResponse.cpp
new file mode 100644
index 0000000..523c504
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/config/RadioConfigResponse.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libradiocompat/RadioConfigResponse.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "ConfigResponse"
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::config;
+
+void RadioConfigResponse::setResponseFunction(
+        std::shared_ptr<aidl::IRadioConfigResponse> callback) {
+    mCallback = callback;
+}
+
+std::shared_ptr<aidl::IRadioConfigResponse> RadioConfigResponse::respond() {
+    return mCallback.get();
+}
+
+Return<void> RadioConfigResponse::getSimSlotsStatusResponse(
+        const V1_0::RadioResponseInfo& info,
+        const hidl_vec<config::V1_0::SimSlotStatus>& slotStatus) {
+    LOG_CALL << info.serial;
+    respond()->getSimSlotsStatusResponse(toAidl(info), toAidl(slotStatus));
+    return {};
+};
+
+Return<void> RadioConfigResponse::getSimSlotsStatusResponse_1_2(
+        const V1_0::RadioResponseInfo& info,
+        const hidl_vec<config::V1_2::SimSlotStatus>& slotStatus) {
+    LOG_CALL << info.serial;
+    respond()->getSimSlotsStatusResponse(toAidl(info), toAidl(slotStatus));
+    return {};
+};
+
+Return<void> RadioConfigResponse::setSimSlotsMappingResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    respond()->setSimSlotsMappingResponse(toAidl(info));
+    return {};
+};
+
+Return<void> RadioConfigResponse::getPhoneCapabilityResponse(
+        const V1_0::RadioResponseInfo& info, const config::V1_1::PhoneCapability& phoneCapability) {
+    LOG_CALL << info.serial;
+    respond()->getPhoneCapabilityResponse(toAidl(info), toAidl(phoneCapability));
+    return {};
+};
+
+Return<void> RadioConfigResponse::setPreferredDataModemResponse(
+        const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    respond()->setPreferredDataModemResponse(toAidl(info));
+    return {};
+};
+
+Return<void> RadioConfigResponse::setModemsConfigResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    respond()->setNumOfLiveModemsResponse(toAidl(info));
+    return {};
+};
+
+Return<void> RadioConfigResponse::getModemsConfigResponse(
+        const V1_0::RadioResponseInfo& info, const config::V1_1::ModemsConfig& modemsConfig) {
+    LOG_CALL << info.serial;
+    respond()->getNumOfLiveModemsResponse(toAidl(info), modemsConfig.numOfLiveModems);
+    return {};
+};
+
+Return<void> RadioConfigResponse::getHalDeviceCapabilitiesResponse(
+        const V1_6::RadioResponseInfo& info, bool modemReducedFeatureSet1) {
+    LOG_CALL << info.serial;
+    respond()->getHalDeviceCapabilitiesResponse(toAidl(info), modemReducedFeatureSet1);
+    return {};
+};
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/config/structs.cpp b/radio/aidl/compat/libradiocompat/config/structs.cpp
new file mode 100644
index 0000000..39ad944
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/config/structs.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "structs.h"
+
+#include "collections.h"
+
+#include <android-base/logging.h>
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::config;
+
+uint32_t toHidl(const aidl::SlotPortMapping& slotPortMapping) {
+    if (slotPortMapping.portId != 0) {
+        LOG(ERROR) << "Port ID " << slotPortMapping.portId << " != 0 not supported by HIDL HAL";
+    }
+    return slotPortMapping.physicalSlotId;
+}
+
+aidl::SimSlotStatus toAidl(const config::V1_0::SimSlotStatus& sst) {
+    return toAidl({sst, ""});
+}
+
+aidl::SimSlotStatus toAidl(const config::V1_2::SimSlotStatus& sst) {
+    const aidl::SimPortInfo portInfo = {
+            .iccId = sst.base.iccid,
+            .logicalSlotId = static_cast<int32_t>(sst.base.logicalSlotId),
+            .portActive = sst.base.slotState == config::V1_0::SlotState::ACTIVE,
+    };
+
+    return {
+            .cardState = static_cast<int32_t>(sst.base.cardState),
+            .atr = sst.base.atr,
+            .eid = sst.eid,
+            .portInfo = {portInfo},
+    };
+}
+
+uint8_t toAidl(const config::V1_1::ModemInfo& info) {
+    return info.modemId;
+}
+
+aidl::PhoneCapability toAidl(const config::V1_1::PhoneCapability& phoneCapability) {
+    return {
+            .maxActiveData = static_cast<int8_t>(phoneCapability.maxActiveData),
+            .maxActiveInternetData = static_cast<int8_t>(phoneCapability.maxActiveInternetData),
+            .isInternetLingeringSupported = phoneCapability.isInternetLingeringSupported,
+            .logicalModemIds = toAidl(phoneCapability.logicalModemList),
+    };
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/config/structs.h b/radio/aidl/compat/libradiocompat/config/structs.h
new file mode 100644
index 0000000..6ea4e4a
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/config/structs.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <aidl/android/hardware/radio/config/PhoneCapability.h>
+#include <aidl/android/hardware/radio/config/SimSlotStatus.h>
+#include <aidl/android/hardware/radio/config/SlotPortMapping.h>
+#include <android/hardware/radio/config/1.1/types.h>
+#include <android/hardware/radio/config/1.2/types.h>
+
+namespace android::hardware::radio::compat {
+
+uint32_t toHidl(const aidl::android::hardware::radio::config::SlotPortMapping& slotPortMapping);
+
+aidl::android::hardware::radio::config::SimSlotStatus  //
+toAidl(const config::V1_0::SimSlotStatus& sst);
+aidl::android::hardware::radio::config::SimSlotStatus  //
+toAidl(const config::V1_2::SimSlotStatus& sst);
+
+uint8_t toAidl(const config::V1_1::ModemInfo& info);
+
+aidl::android::hardware::radio::config::PhoneCapability  //
+toAidl(const config::V1_1::PhoneCapability& pc);
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/data/RadioData.cpp b/radio/aidl/compat/libradiocompat/data/RadioData.cpp
new file mode 100644
index 0000000..51f5543
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/data/RadioData.cpp
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libradiocompat/RadioData.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "Data"
+
+namespace android::hardware::radio::compat {
+
+using ::ndk::ScopedAStatus;
+namespace aidl = ::aidl::android::hardware::radio::data;
+namespace aidlCommon = ::aidl::android::hardware::radio;
+constexpr auto ok = &ScopedAStatus::ok;
+
+std::shared_ptr<aidl::IRadioDataResponse> RadioData::respond() {
+    return mCallbackManager->response().dataCb();
+}
+
+ScopedAStatus RadioData::allocatePduSessionId(int32_t serial) {
+    LOG_CALL << serial;
+    if (mHal1_6) {
+        mHal1_6->allocatePduSessionId(serial);
+    } else {
+        respond()->allocatePduSessionIdResponse(notSupported(serial), 0);
+    }
+    return ok();
+}
+
+ScopedAStatus RadioData::cancelHandover(int32_t serial, int32_t callId) {
+    LOG_CALL << serial;
+    if (mHal1_6) {
+        mHal1_6->cancelHandover(serial, callId);
+    } else {
+        respond()->cancelHandoverResponse(notSupported(serial));
+    }
+    return ok();
+}
+
+ScopedAStatus RadioData::deactivateDataCall(int32_t serial, int32_t cid,
+                                            aidl::DataRequestReason reason) {
+    LOG_CALL << serial;
+    mHal1_5->deactivateDataCall_1_2(serial, cid, V1_2::DataRequestReason(reason));
+    return ok();
+}
+
+ScopedAStatus RadioData::getDataCallList(int32_t serial) {
+    LOG_CALL << serial;
+    if (mHal1_6) {
+        mHal1_6->getDataCallList_1_6(serial);
+    } else {
+        mHal1_5->getDataCallList(serial);
+    }
+    return ok();
+}
+
+ScopedAStatus RadioData::getSlicingConfig(int32_t serial) {
+    LOG_CALL << serial;
+    if (mHal1_6) {
+        mHal1_6->getSlicingConfig(serial);
+    } else {
+        respond()->getSlicingConfigResponse(notSupported(serial), {});
+    }
+    return ok();
+}
+
+ScopedAStatus RadioData::releasePduSessionId(int32_t serial, int32_t id) {
+    LOG_CALL << serial;
+    if (mHal1_6) {
+        mHal1_6->releasePduSessionId(serial, id);
+    } else {
+        respond()->releasePduSessionIdResponse(notSupported(serial));
+    }
+    return ok();
+}
+
+ScopedAStatus RadioData::responseAcknowledgement() {
+    LOG_CALL;
+    mHal1_5->responseAcknowledgement();
+    return ok();
+}
+
+ScopedAStatus RadioData::setDataAllowed(int32_t serial, bool allow) {
+    LOG_CALL << serial;
+    mHal1_5->setDataAllowed(serial, allow);
+    return ok();
+}
+
+ScopedAStatus RadioData::setDataProfile(int32_t serial,
+                                        const std::vector<aidl::DataProfileInfo>& profiles) {
+    LOG_CALL << serial;
+    mHal1_5->setDataProfile_1_5(serial, toHidl(profiles));
+    return ok();
+}
+
+ScopedAStatus RadioData::setDataThrottling(int32_t serial, aidl::DataThrottlingAction dta,
+                                           int64_t completionDurationMs) {
+    LOG_CALL << serial;
+    if (mHal1_6) {
+        mHal1_6->setDataThrottling(serial, V1_6::DataThrottlingAction(dta), completionDurationMs);
+    } else {
+        respond()->setDataThrottlingResponse(notSupported(serial));
+    }
+    return ok();
+}
+
+ScopedAStatus RadioData::setInitialAttachApn(int32_t serial,
+                                             const std::optional<aidl::DataProfileInfo>& info) {
+    LOG_CALL << serial;
+    mHal1_5->setInitialAttachApn_1_5(serial, toHidl(info.value()));
+    return ok();
+}
+
+ScopedAStatus RadioData::setResponseFunctions(
+        const std::shared_ptr<aidl::IRadioDataResponse>& response,
+        const std::shared_ptr<aidl::IRadioDataIndication>& indication) {
+    LOG_CALL << response << ' ' << indication;
+    mCallbackManager->setResponseFunctions(response, indication);
+    return ok();
+}
+
+ScopedAStatus RadioData::setupDataCall(int32_t serial, aidlCommon::AccessNetwork accessNetwork,
+                                       const aidl::DataProfileInfo& dataProfileInfo,
+                                       bool roamingAllowed, aidl::DataRequestReason reason,
+                                       const std::vector<aidl::LinkAddress>& addresses,
+                                       const std::vector<std::string>& dnses, int32_t pduSessId,
+                                       const std::optional<aidl::SliceInfo>& sliceInfo,
+                                       bool matchAllRuleAllowed) {
+    if (mHal1_6) {
+        mHal1_6->setupDataCall_1_6(
+                serial, V1_5::AccessNetwork(accessNetwork), toHidl(dataProfileInfo), roamingAllowed,
+                V1_2::DataRequestReason(reason), toHidl(addresses), toHidl(dnses), pduSessId,
+                toHidl<V1_6::OptionalSliceInfo>(sliceInfo),
+                toHidl<V1_6::OptionalTrafficDescriptor>(dataProfileInfo.trafficDescriptor),
+                matchAllRuleAllowed);
+        mContext->addDataProfile(dataProfileInfo);
+    } else {
+        mHal1_5->setupDataCall_1_5(
+                serial, V1_5::AccessNetwork(accessNetwork), toHidl(dataProfileInfo), roamingAllowed,
+                V1_2::DataRequestReason(reason), toHidl(addresses), toHidl(dnses));
+    }
+    return ok();
+}
+
+ScopedAStatus RadioData::startHandover(int32_t serial, int32_t callId) {
+    LOG_CALL << serial;
+    if (mHal1_6) {
+        mHal1_6->startHandover(serial, callId);
+    } else {
+        respond()->startHandoverResponse(notSupported(serial));
+    }
+    return ok();
+}
+
+ScopedAStatus RadioData::startKeepalive(int32_t serial, const aidl::KeepaliveRequest& keepalive) {
+    LOG_CALL << serial;
+    mHal1_5->startKeepalive(serial, toHidl(keepalive));
+    return ok();
+}
+
+ScopedAStatus RadioData::stopKeepalive(int32_t serial, int32_t sessionHandle) {
+    LOG_CALL << serial;
+    mHal1_5->stopKeepalive(serial, sessionHandle);
+    return ok();
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/data/RadioIndication-data.cpp b/radio/aidl/compat/libradiocompat/data/RadioIndication-data.cpp
new file mode 100644
index 0000000..602bb39
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/data/RadioIndication-data.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libradiocompat/RadioIndication.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "DataIndication"
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::data;
+
+void RadioIndication::setResponseFunction(std::shared_ptr<aidl::IRadioDataIndication> dataCb) {
+    mDataCb = dataCb;
+}
+
+std::shared_ptr<aidl::IRadioDataIndication> RadioIndication::dataCb() {
+    return mDataCb.get();
+}
+
+Return<void> RadioIndication::dataCallListChanged(V1_0::RadioIndicationType type,
+                                                  const hidl_vec<V1_0::SetupDataCallResult>&) {
+    LOG_CALL << type;
+    LOG(ERROR) << "IRadio HAL 1.0 not supported";
+    return {};
+}
+
+Return<void> RadioIndication::dataCallListChanged_1_4(V1_0::RadioIndicationType type,
+                                                      const hidl_vec<V1_4::SetupDataCallResult>&) {
+    LOG_CALL << type;
+    LOG(ERROR) << "IRadio HAL 1.4 not supported";
+    return {};
+}
+
+Return<void> RadioIndication::dataCallListChanged_1_5(
+        V1_0::RadioIndicationType type, const hidl_vec<V1_5::SetupDataCallResult>& dcList) {
+    LOG_CALL << type;
+    dataCb()->dataCallListChanged(toAidl(type), toAidl(dcList));
+    return {};
+}
+
+Return<void> RadioIndication::dataCallListChanged_1_6(
+        V1_0::RadioIndicationType type, const hidl_vec<V1_6::SetupDataCallResult>& dcList) {
+    LOG_CALL << type;
+    dataCb()->dataCallListChanged(toAidl(type), toAidl(dcList));
+    return {};
+}
+
+Return<void> RadioIndication::keepaliveStatus(V1_0::RadioIndicationType type,
+                                              const V1_1::KeepaliveStatus& status) {
+    LOG_CALL << type;
+    dataCb()->keepaliveStatus(toAidl(type), toAidl(status));
+    return {};
+}
+
+Return<void> RadioIndication::pcoData(V1_0::RadioIndicationType type,
+                                      const V1_0::PcoDataInfo& pco) {
+    LOG_CALL << type;
+    dataCb()->pcoData(toAidl(type), toAidl(pco));
+    return {};
+}
+
+Return<void> RadioIndication::unthrottleApn(V1_0::RadioIndicationType type,
+                                            const hidl_string& apn) {
+    LOG_CALL << type;
+    dataCb()->unthrottleApn(toAidl(type), mContext->getDataProfile(apn));
+    return {};
+}
+
+Return<void> RadioIndication::slicingConfigChanged(V1_0::RadioIndicationType type,
+                                                   const V1_6::SlicingConfig& slicingConfig) {
+    LOG_CALL << type;
+    dataCb()->slicingConfigChanged(toAidl(type), toAidl(slicingConfig));
+    return {};
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/data/RadioResponse-data.cpp b/radio/aidl/compat/libradiocompat/data/RadioResponse-data.cpp
new file mode 100644
index 0000000..0bfa2df
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/data/RadioResponse-data.cpp
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libradiocompat/RadioResponse.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "DataResponse"
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::data;
+
+void RadioResponse::setResponseFunction(std::shared_ptr<aidl::IRadioDataResponse> dataCb) {
+    mDataCb = dataCb;
+}
+
+std::shared_ptr<aidl::IRadioDataResponse> RadioResponse::dataCb() {
+    return mDataCb.get();
+}
+
+Return<void> RadioResponse::allocatePduSessionIdResponse(const V1_6::RadioResponseInfo& info,
+                                                         int32_t id) {
+    LOG_CALL << info.serial;
+    dataCb()->allocatePduSessionIdResponse(toAidl(info), id);
+    return {};
+}
+
+Return<void> RadioResponse::cancelHandoverResponse(const V1_6::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    dataCb()->cancelHandoverResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::deactivateDataCallResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    dataCb()->deactivateDataCallResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::getDataCallListResponse(const V1_0::RadioResponseInfo& info,
+                                                    const hidl_vec<V1_0::SetupDataCallResult>&) {
+    LOG_CALL << info.serial;
+    LOG(ERROR) << "IRadio HAL 1.0 not supported";
+    return {};
+}
+
+Return<void> RadioResponse::getDataCallListResponse_1_4(
+        const V1_0::RadioResponseInfo& info, const hidl_vec<V1_4::SetupDataCallResult>&) {
+    LOG_CALL << info.serial;
+    LOG(ERROR) << "IRadio HAL 1.4 not supported";
+    return {};
+}
+
+Return<void> RadioResponse::getDataCallListResponse_1_5(
+        const V1_0::RadioResponseInfo& info,
+        const hidl_vec<V1_5::SetupDataCallResult>& dcResponse) {
+    LOG_CALL << info.serial;
+    dataCb()->getDataCallListResponse(toAidl(info), toAidl(dcResponse));
+    return {};
+}
+
+Return<void> RadioResponse::getDataCallListResponse_1_6(
+        const V1_6::RadioResponseInfo& info,
+        const hidl_vec<V1_6::SetupDataCallResult>& dcResponse) {
+    LOG_CALL << info.serial;
+    dataCb()->getDataCallListResponse(toAidl(info), toAidl(dcResponse));
+    return {};
+}
+
+Return<void> RadioResponse::getSlicingConfigResponse(const V1_6::RadioResponseInfo& info,
+                                                     const V1_6::SlicingConfig& slicingConfig) {
+    LOG_CALL << info.serial;
+    dataCb()->getSlicingConfigResponse(toAidl(info), toAidl(slicingConfig));
+    return {};
+}
+
+Return<void> RadioResponse::releasePduSessionIdResponse(const V1_6::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    dataCb()->releasePduSessionIdResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setDataAllowedResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    dataCb()->setDataAllowedResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setDataProfileResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    dataCb()->setDataProfileResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setDataProfileResponse_1_5(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    dataCb()->setDataProfileResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setDataThrottlingResponse(const V1_6::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    dataCb()->setDataThrottlingResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setInitialAttachApnResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    dataCb()->setInitialAttachApnResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setInitialAttachApnResponse_1_5(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    dataCb()->setInitialAttachApnResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setupDataCallResponse(const V1_0::RadioResponseInfo& info,
+                                                  const V1_0::SetupDataCallResult&) {
+    LOG_CALL << info.serial;
+    LOG(ERROR) << "IRadio HAL 1.0 not supported";
+    return {};
+}
+
+Return<void> RadioResponse::setupDataCallResponse_1_4(const V1_0::RadioResponseInfo& info,
+                                                      const V1_4::SetupDataCallResult&) {
+    LOG_CALL << info.serial;
+    LOG(ERROR) << "IRadio HAL 1.0 not supported";
+    return {};
+}
+
+Return<void> RadioResponse::setupDataCallResponse_1_5(const V1_0::RadioResponseInfo& info,
+                                                      const V1_5::SetupDataCallResult& dcResponse) {
+    LOG_CALL << info.serial;
+    dataCb()->setupDataCallResponse(toAidl(info), toAidl(dcResponse));
+    return {};
+}
+
+Return<void> RadioResponse::setupDataCallResponse_1_6(const V1_6::RadioResponseInfo& info,
+                                                      const V1_6::SetupDataCallResult& dcResponse) {
+    LOG_CALL << info.serial;
+    dataCb()->setupDataCallResponse(toAidl(info), toAidl(dcResponse));
+    return {};
+}
+
+Return<void> RadioResponse::startHandoverResponse(const V1_6::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    dataCb()->startHandoverResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::startKeepaliveResponse(const V1_0::RadioResponseInfo& info,
+                                                   const V1_1::KeepaliveStatus& status) {
+    LOG_CALL << info.serial;
+    dataCb()->startKeepaliveResponse(toAidl(info), toAidl(status));
+    return {};
+}
+
+Return<void> RadioResponse::stopKeepaliveResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    dataCb()->stopKeepaliveResponse(toAidl(info));
+    return {};
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/data/structs.cpp b/radio/aidl/compat/libradiocompat/data/structs.cpp
new file mode 100644
index 0000000..4ff89a1
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/data/structs.cpp
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "structs.h"
+
+#include "commonStructs.h"
+
+#include "collections.h"
+
+#include <android-base/logging.h>
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::data;
+
+V1_5::DataProfileInfo toHidl(const aidl::DataProfileInfo& info) {
+    return {
+            .profileId = 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},
+            .user = info.user,
+            .password = info.password,
+            .type = V1_0::DataProfileInfoType{info.type},
+            .maxConnsTime = info.maxConnsTime,
+            .maxConns = info.maxConns,
+            .waitTime = info.waitTime,
+            .enabled = info.enabled,
+            .supportedApnTypesBitmap = toHidlBitfield<V1_5::ApnTypes>(info.supportedApnTypesBitmap),
+            .bearerBitmap = toHidlBitfield<V1_4::RadioAccessFamily>(info.bearerBitmap),
+            .mtuV4 = info.mtuV4,
+            .mtuV6 = info.mtuV6,
+            .preferred = info.preferred,
+            .persistent = info.persistent,
+    };
+}
+
+V1_5::LinkAddress toHidl(const aidl::LinkAddress& addr) {
+    return {
+            .address = addr.address,
+            .properties = addr.addressProperties,
+            .deprecationTime = static_cast<uint64_t>(addr.deprecationTime),
+            .expirationTime = static_cast<uint64_t>(addr.expirationTime),
+    };
+}
+
+aidl::SliceInfo toAidl(const V1_6::SliceInfo& info) {
+    return {
+            .sliceServiceType = static_cast<int8_t>(info.sst),
+            .sliceDifferentiator = info.sliceDifferentiator,
+            .mappedHplmnSst = static_cast<int8_t>(info.mappedHplmnSst),
+            .mappedHplmnSd = info.mappedHplmnSD,
+            .status = static_cast<int8_t>(info.status),
+    };
+}
+
+V1_6::SliceInfo toHidl(const aidl::SliceInfo& info) {
+    return {
+            .sst = static_cast<V1_6::SliceServiceType>(info.sliceServiceType),
+            .sliceDifferentiator = info.sliceDifferentiator,
+            .mappedHplmnSst = static_cast<V1_6::SliceServiceType>(info.mappedHplmnSst),
+            .mappedHplmnSD = info.mappedHplmnSd,
+            .status = V1_6::SliceStatus{info.status},
+    };
+}
+
+aidl::TrafficDescriptor toAidl(const V1_6::TrafficDescriptor& descr) {
+    return {
+            .dnn = toAidl(descr.dnn),
+            .osAppId = toAidl(descr.osAppId),
+    };
+}
+
+V1_6::TrafficDescriptor toHidl(const aidl::TrafficDescriptor& descr) {
+    return {
+            .dnn = toHidl<V1_6::OptionalDnn>(descr.dnn),
+            .osAppId = toHidl<V1_6::OptionalOsAppId>(descr.osAppId),
+    };
+}
+
+aidl::OsAppId toAidl(const V1_6::OsAppId& appId) {
+    return {
+            .osAppId = appId.osAppId,
+    };
+}
+
+V1_6::OsAppId toHidl(const aidl::OsAppId& appId) {
+    return {
+            .osAppId = appId.osAppId,
+    };
+}
+
+V1_1::KeepaliveRequest toHidl(const aidl::KeepaliveRequest& keep) {
+    return {
+            .type = V1_1::KeepaliveType{keep.type},
+            .sourceAddress = keep.sourceAddress,
+            .sourcePort = keep.sourcePort,
+            .destinationAddress = keep.destinationAddress,
+            .destinationPort = keep.destinationPort,
+            .maxKeepaliveIntervalMillis = keep.maxKeepaliveIntervalMillis,
+            .cid = keep.cid,
+    };
+}
+
+static aidl::QosBandwidth toAidl(const V1_6::QosBandwidth& bw) {
+    return {
+            .maxBitrateKbps = static_cast<int32_t>(bw.maxBitrateKbps),
+            .guaranteedBitrateKbps = static_cast<int32_t>(bw.guaranteedBitrateKbps),
+    };
+}
+
+static aidl::EpsQos toAidl(const V1_6::EpsQos& qos) {
+    return {
+            .qci = qos.qci,
+            .downlink = toAidl(qos.downlink),
+            .uplink = toAidl(qos.uplink),
+    };
+}
+
+static aidl::NrQos toAidl(const V1_6::NrQos& qos) {
+    return {
+            .fiveQi = qos.fiveQi,
+            .downlink = toAidl(qos.downlink),
+            .uplink = toAidl(qos.uplink),
+            .qfi = static_cast<int8_t>(qos.qfi),
+            .averagingWindowMs = qos.averagingWindowMs,
+    };
+}
+
+static std::variant<bool, aidl::EpsQos, aidl::NrQos> toAidl(const V1_6::Qos& qos) {
+    if (qos.getDiscriminator() == V1_6::Qos::hidl_discriminator::eps) return toAidl(qos.eps());
+    if (qos.getDiscriminator() == V1_6::Qos::hidl_discriminator::nr) return toAidl(qos.nr());
+    return false;
+}
+
+aidl::SetupDataCallResult toAidl(const V1_5::SetupDataCallResult& res) {
+    return {
+            .cause = aidl::DataCallFailCause(res.cause),
+            .suggestedRetryTime = res.suggestedRetryTime,
+            .cid = res.cid,
+            .active = static_cast<int32_t>(res.active),
+            .type = aidl::PdpProtocolType(res.type),
+            .ifname = res.ifname,
+            .addresses = toAidl(res.addresses),
+            .dnses = toAidl(res.dnses),
+            .gateways = toAidl(res.gateways),
+            .pcscf = toAidl(res.pcscf),
+            .mtuV4 = res.mtuV4,
+            .mtuV6 = res.mtuV6,
+    };
+}
+
+aidl::SetupDataCallResult toAidl(const V1_6::SetupDataCallResult& res) {
+    return {
+            .cause = aidl::DataCallFailCause(res.cause),
+            .suggestedRetryTime = res.suggestedRetryTime,
+            .cid = res.cid,
+            .active = static_cast<int32_t>(res.active),
+            .type = aidl::PdpProtocolType(res.type),
+            .ifname = res.ifname,
+            .addresses = toAidl(res.addresses),
+            .dnses = toAidl(res.dnses),
+            .gateways = toAidl(res.gateways),
+            .pcscf = toAidl(res.pcscf),
+            .mtuV4 = res.mtuV4,
+            .mtuV6 = res.mtuV6,
+            .defaultQos = toAidl(res.defaultQos),
+            .qosSessions = toAidl(res.qosSessions),
+            .handoverFailureMode = static_cast<int8_t>(res.handoverFailureMode),
+            .pduSessionId = res.pduSessionId,
+            .sliceInfo = toAidl(res.sliceInfo),
+            .trafficDescriptors = toAidl(res.trafficDescriptors),
+    };
+}
+
+aidl::LinkAddress toAidl(const V1_5::LinkAddress& addr) {
+    return {
+            .address = addr.address,
+            .addressProperties = addr.properties,
+            .deprecationTime = static_cast<int64_t>(addr.deprecationTime),
+            .expirationTime = static_cast<int64_t>(addr.expirationTime),
+    };
+}
+
+aidl::QosSession toAidl(const V1_6::QosSession& sess) {
+    return {
+            .qosSessionId = sess.qosSessionId,
+            .qos = toAidl(sess.qos),
+            .qosFilters = toAidl(sess.qosFilters),
+    };
+}
+
+static aidl::PortRange toAidl(const V1_6::PortRange& range) {
+    return {
+            .start = range.start,
+            .end = range.end,
+    };
+}
+
+static std::optional<aidl::PortRange> toAidl(const V1_6::MaybePort& opt) {
+    if (opt.getDiscriminator() == V1_6::MaybePort::hidl_discriminator::noinit) return std::nullopt;
+    return toAidl(opt.range());  // can't use MaybeX template - this field is not named "value"
+}
+
+aidl::QosFilter toAidl(const V1_6::QosFilter& filter) {
+    return {
+            .localAddresses = toAidl(filter.localAddresses),
+            .remoteAddresses = toAidl(filter.remoteAddresses),
+            .localPort = toAidl(filter.localPort),
+            .remotePort = toAidl(filter.remotePort),
+            .protocol = static_cast<int8_t>(filter.protocol),
+            .tos = toAidlVariant(filter.tos),
+            .flowLabel = toAidlVariant(filter.flowLabel),
+            .spi = toAidlVariant(filter.spi),
+            .direction = static_cast<int8_t>(filter.direction),
+            .precedence = filter.precedence,
+    };
+}
+
+aidl::KeepaliveStatus toAidl(const V1_1::KeepaliveStatus& status) {
+    return {
+            .sessionHandle = status.sessionHandle,
+            .code = static_cast<int32_t>(status.code),
+    };
+}
+
+aidl::PcoDataInfo toAidl(const V1_0::PcoDataInfo& info) {
+    return {
+            .cid = info.cid,
+            .bearerProto = info.bearerProto,
+            .pcoId = info.pcoId,
+            .contents = info.contents,
+    };
+}
+
+aidl::SlicingConfig toAidl(const V1_6::SlicingConfig& cfg) {
+    return {
+            .urspRules = toAidl(cfg.urspRules),
+            .sliceInfo = toAidl(cfg.sliceInfo),
+    };
+}
+
+aidl::UrspRule toAidl(const V1_6::UrspRule& rule) {
+    return {
+            .precedence = rule.precedence,
+            .trafficDescriptors = toAidl(rule.trafficDescriptors),
+            .routeSelectionDescriptor = toAidl(rule.routeSelectionDescriptor),
+    };
+}
+
+static int8_t toAidl(const V1_6::OptionalSscMode& opt) {
+    if (opt.getDiscriminator() == V1_6::OptionalSscMode::hidl_discriminator::noinit) {
+        return aidl::RouteSelectionDescriptor::SSC_MODE_UNKNOWN;
+    }
+    return static_cast<int8_t>(opt.value());
+}
+
+static aidl::PdpProtocolType toAidl(const V1_6::OptionalPdpProtocolType& opt) {
+    using discriminator = V1_6::OptionalPdpProtocolType::hidl_discriminator;
+    if (opt.getDiscriminator() == discriminator::noinit) return aidl::PdpProtocolType::UNKNOWN;
+    return aidl::PdpProtocolType(opt.value());
+}
+
+aidl::RouteSelectionDescriptor toAidl(const V1_6::RouteSelectionDescriptor& descr) {
+    return {
+            .precedence = static_cast<int8_t>(descr.precedence),
+            .sessionType = toAidl(descr.sessionType),
+            .sscMode = toAidl(descr.sscMode),
+            .sliceInfo = toAidl(descr.sliceInfo),
+            .dnn = toAidl(descr.dnn),
+    };
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/data/structs.h b/radio/aidl/compat/libradiocompat/data/structs.h
new file mode 100644
index 0000000..60fad57
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/data/structs.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <aidl/android/hardware/radio/data/DataProfileInfo.h>
+#include <aidl/android/hardware/radio/data/KeepaliveRequest.h>
+#include <aidl/android/hardware/radio/data/KeepaliveStatus.h>
+#include <aidl/android/hardware/radio/data/LinkAddress.h>
+#include <aidl/android/hardware/radio/data/OsAppId.h>
+#include <aidl/android/hardware/radio/data/PcoDataInfo.h>
+#include <aidl/android/hardware/radio/data/RouteSelectionDescriptor.h>
+#include <aidl/android/hardware/radio/data/SetupDataCallResult.h>
+#include <aidl/android/hardware/radio/data/SliceInfo.h>
+#include <aidl/android/hardware/radio/data/SlicingConfig.h>
+#include <aidl/android/hardware/radio/data/TrafficDescriptor.h>
+#include <aidl/android/hardware/radio/data/UrspRule.h>
+#include <android/hardware/radio/1.6/types.h>
+
+namespace android::hardware::radio::compat {
+
+V1_5::DataProfileInfo toHidl(const ::aidl::android::hardware::radio::data::DataProfileInfo& info);
+
+V1_5::LinkAddress toHidl(const ::aidl::android::hardware::radio::data::LinkAddress& addr);
+
+::aidl::android::hardware::radio::data::SliceInfo toAidl(const V1_6::SliceInfo& info);
+V1_6::SliceInfo toHidl(const ::aidl::android::hardware::radio::data::SliceInfo& info);
+
+::aidl::android::hardware::radio::data::TrafficDescriptor toAidl(const V1_6::TrafficDescriptor& td);
+V1_6::TrafficDescriptor toHidl(const ::aidl::android::hardware::radio::data::TrafficDescriptor& td);
+
+V1_1::KeepaliveRequest toHidl(const ::aidl::android::hardware::radio::data::KeepaliveRequest& keep);
+
+::aidl::android::hardware::radio::data::OsAppId toAidl(const V1_6::OsAppId& appId);
+V1_6::OsAppId toHidl(const ::aidl::android::hardware::radio::data::OsAppId& appId);
+
+::aidl::android::hardware::radio::data::SetupDataCallResult  //
+toAidl(const V1_5::SetupDataCallResult& res);
+::aidl::android::hardware::radio::data::SetupDataCallResult  //
+toAidl(const V1_6::SetupDataCallResult& res);
+
+::aidl::android::hardware::radio::data::LinkAddress toAidl(const V1_5::LinkAddress& addr);
+
+::aidl::android::hardware::radio::data::QosSession toAidl(const V1_6::QosSession& session);
+
+::aidl::android::hardware::radio::data::QosFilter toAidl(const V1_6::QosFilter& filter);
+
+::aidl::android::hardware::radio::data::KeepaliveStatus toAidl(const V1_1::KeepaliveStatus& status);
+
+::aidl::android::hardware::radio::data::PcoDataInfo toAidl(const V1_0::PcoDataInfo& info);
+
+::aidl::android::hardware::radio::data::SlicingConfig toAidl(const V1_6::SlicingConfig& cfg);
+
+::aidl::android::hardware::radio::data::UrspRule toAidl(const V1_6::UrspRule& rule);
+
+::aidl::android::hardware::radio::data::RouteSelectionDescriptor  //
+toAidl(const V1_6::RouteSelectionDescriptor& descr);
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/debug.h b/radio/aidl/compat/libradiocompat/debug.h
new file mode 100644
index 0000000..cb773bf
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/debug.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <android-base/logging.h>
+
+namespace android::hardware::radio::compat {
+
+namespace debug {
+
+static constexpr bool kSuperVerbose = true;
+
+#define LOG_CALL \
+    if constexpr (debug::kSuperVerbose) LOG(VERBOSE) << (RADIO_MODULE ".") << __func__ << ' '
+
+}  // namespace debug
+
+inline std::ostream& operator<<(std::ostream& os, const V1_0::RadioIndicationType& type) {
+    return os << static_cast<int>(type);
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/CallbackManager.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/CallbackManager.h
new file mode 100644
index 0000000..f1a7b49
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/CallbackManager.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include "DriverContext.h"
+#include "RadioIndication.h"
+#include "RadioResponse.h"
+
+#include <android-base/logging.h>
+#include <android/hardware/radio/1.6/IRadio.h>
+
+#include <thread>
+
+namespace android::hardware::radio::compat {
+
+class CallbackManager {
+    sp<V1_5::IRadio> mHidlHal;
+    sp<RadioResponse> mRadioResponse;
+    sp<RadioIndication> mRadioIndication;
+
+    std::thread mDelayedSetterThread;
+    std::mutex mDelayedSetterGuard;
+    std::optional<std::chrono::time_point<std::chrono::steady_clock>> mDelayedSetterDeadline
+            GUARDED_BY(mDelayedSetterGuard);
+    std::condition_variable mDelayedSetterCv GUARDED_BY(mDelayedSetterGuard);
+    bool mDestroy GUARDED_BY(mDelayedSetterGuard) = false;
+
+    void setResponseFunctionsDelayed();
+    void delayedSetterThread();
+
+  public:
+    CallbackManager(std::shared_ptr<DriverContext> context, sp<V1_5::IRadio> hidlHal);
+    ~CallbackManager();
+
+    RadioResponse& response() const;
+
+    template <typename ResponseType, typename IndicationType>
+    void setResponseFunctions(const std::shared_ptr<ResponseType>& response,
+                              const std::shared_ptr<IndicationType>& indication) {
+        CHECK(response);
+        CHECK(indication);
+
+        mRadioResponse->setResponseFunction(response);
+        mRadioIndication->setResponseFunction(indication);
+        setResponseFunctionsDelayed();
+    }
+};
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/DriverContext.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/DriverContext.h
new file mode 100644
index 0000000..6833aca
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/DriverContext.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <aidl/android/hardware/radio/data/DataProfileInfo.h>
+
+#include <map>
+
+namespace android::hardware::radio::compat {
+
+class DriverContext {
+    std::map<std::string, ::aidl::android::hardware::radio::data::DataProfileInfo> mDataProfiles;
+
+  public:
+    void addDataProfile(const ::aidl::android::hardware::radio::data::DataProfileInfo& profile);
+    ::aidl::android::hardware::radio::data::DataProfileInfo getDataProfile(const std::string& apn);
+};
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/GuaranteedCallback.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/GuaranteedCallback.h
new file mode 100644
index 0000000..0b6ee11
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/GuaranteedCallback.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <android-base/logging.h>
+#include <android/binder_interface_utils.h>
+#include <utils/Mutex.h>
+
+namespace android::hardware::radio::compat {
+
+template <typename Interface, typename DefaultImplementation, bool isIndication = false>
+class GuaranteedCallback {
+    mutable std::mutex mCallbackGuard;
+    std::shared_ptr<Interface> mCallback GUARDED_BY(mCallbackGuard);
+
+  public:
+    GuaranteedCallback<Interface, DefaultImplementation, isIndication>& operator=(
+            const std::shared_ptr<Interface>& callback) {
+        CHECK(callback);
+        const std::lock_guard<std::mutex> lock(mCallbackGuard);
+        mCallback = callback;
+        return *this;
+    }
+
+    std::shared_ptr<Interface> get() {
+        if (mCallback) return mCallback;
+        const std::lock_guard<std::mutex> lock(mCallbackGuard);
+        if (mCallback) return mCallback;
+
+        LOG(isIndication ? WARNING : ERROR) << "Callback is not set";
+        return mCallback = ndk::SharedRefBase::make<DefaultImplementation>();
+    }
+
+    operator bool() const { return mCallback != nullptr; }
+};
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioCompatBase.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioCompatBase.h
new file mode 100644
index 0000000..eb22fff
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioCompatBase.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include "CallbackManager.h"
+#include "DriverContext.h"
+
+#include <android/hardware/radio/1.6/IRadio.h>
+
+namespace android::hardware::radio::compat {
+
+class RadioCompatBase {
+  protected:
+    std::shared_ptr<DriverContext> mContext;
+
+    sp<V1_5::IRadio> mHal1_5;
+    sp<V1_6::IRadio> mHal1_6;
+
+    std::shared_ptr<CallbackManager> mCallbackManager;
+
+  public:
+    RadioCompatBase(std::shared_ptr<DriverContext> context, sp<V1_5::IRadio> hidlHal,
+                    std::shared_ptr<CallbackManager> cbMgr);
+};
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfig.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfig.h
new file mode 100644
index 0000000..bbfff61
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfig.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include "RadioConfigIndication.h"
+#include "RadioConfigResponse.h"
+
+#include <aidl/android/hardware/radio/config/BnRadioConfig.h>
+#include <android/hardware/radio/config/1.2/IRadioConfigIndication.h>
+#include <android/hardware/radio/config/1.3/IRadioConfig.h>
+#include <android/hardware/radio/config/1.3/IRadioConfigResponse.h>
+
+namespace android::hardware::radio::compat {
+
+/**
+ * HAL translator from HIDL IRadioConfig to AIDL IRadioConfig.
+ *
+ * This class wraps existing HIDL implementation (either a binder stub or real
+ * class implementing the HAL) and implements AIDL HAL. It's up to the caller to
+ * fetch source implementation and publish resulting HAL instance.
+ */
+class RadioConfig : public aidl::android::hardware::radio::config::BnRadioConfig {
+    const sp<config::V1_1::IRadioConfig> mHal1_1;
+    const sp<config::V1_3::IRadioConfig> mHal1_3;
+
+    const sp<RadioConfigResponse> mRadioConfigResponse;
+    const sp<RadioConfigIndication> mRadioConfigIndication;
+
+    std::shared_ptr<::aidl::android::hardware::radio::config::IRadioConfigResponse> respond();
+
+    ::ndk::ScopedAStatus getHalDeviceCapabilities(int32_t serial) override;
+    ::ndk::ScopedAStatus getNumOfLiveModems(int32_t serial) override;
+    ::ndk::ScopedAStatus getPhoneCapability(int32_t serial) override;
+    ::ndk::ScopedAStatus getSimSlotsStatus(int32_t serial) override;
+    ::ndk::ScopedAStatus setNumOfLiveModems(int32_t serial, int8_t numOfLiveModems) override;
+    ::ndk::ScopedAStatus setPreferredDataModem(int32_t serial, int8_t modemId) override;
+    ::ndk::ScopedAStatus setResponseFunctions(
+            const std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfigResponse>&
+                    radioConfigResponse,
+            const std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfigIndication>&
+                    radioConfigIndication) override;
+    ::ndk::ScopedAStatus setSimSlotsMapping(
+            int32_t serial,
+            const std::vector<aidl::android::hardware::radio::config::SlotPortMapping>& slotMap)
+            override;
+
+  public:
+    /**
+     * Constructs AIDL IRadioConfig instance wrapping existing HIDL IRadioConfig instance.
+     *
+     * \param hidlHal existing HIDL IRadioConfig HAL instance
+     */
+    RadioConfig(sp<config::V1_1::IRadioConfig> hidlHal);
+};
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfigIndication.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfigIndication.h
new file mode 100644
index 0000000..d256a87
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfigIndication.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include "GuaranteedCallback.h"
+
+#include <aidl/android/hardware/radio/config/IRadioConfigIndication.h>
+#include <android/hardware/radio/config/1.2/IRadioConfigIndication.h>
+
+namespace android::hardware::radio::compat {
+
+class RadioConfigIndication : public config::V1_2::IRadioConfigIndication {
+    GuaranteedCallback<aidl::android::hardware::radio::config::IRadioConfigIndication,
+                       aidl::android::hardware::radio::config::IRadioConfigIndicationDefault, true>
+            mCallback;
+
+    Return<void> simSlotsStatusChanged(
+            V1_0::RadioIndicationType type,
+            const hidl_vec<config::V1_0::SimSlotStatus>& slotStatus) override;
+    Return<void> simSlotsStatusChanged_1_2(
+            V1_0::RadioIndicationType type,
+            const hidl_vec<config::V1_2::SimSlotStatus>& slotStatus) override;
+
+  public:
+    void setResponseFunction(
+            std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfigIndication> cb);
+
+    std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfigIndication> indicate();
+};
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfigResponse.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfigResponse.h
new file mode 100644
index 0000000..dc86da2
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioConfigResponse.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include "GuaranteedCallback.h"
+
+#include <aidl/android/hardware/radio/config/IRadioConfigResponse.h>
+#include <android/hardware/radio/config/1.3/IRadioConfigResponse.h>
+
+namespace android::hardware::radio::compat {
+
+class RadioConfigResponse : public config::V1_3::IRadioConfigResponse {
+    GuaranteedCallback<aidl::android::hardware::radio::config::IRadioConfigResponse,
+                       aidl::android::hardware::radio::config::IRadioConfigResponseDefault>
+            mCallback;
+
+    Return<void> getSimSlotsStatusResponse(
+            const V1_0::RadioResponseInfo& info,
+            const hidl_vec<config::V1_0::SimSlotStatus>& slotStatus) override;
+    Return<void> setSimSlotsMappingResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> getPhoneCapabilityResponse(
+            const V1_0::RadioResponseInfo& info,
+            const config::V1_1::PhoneCapability& phoneCapability) override;
+    Return<void> setPreferredDataModemResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> setModemsConfigResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> getModemsConfigResponse(const V1_0::RadioResponseInfo& info,
+                                         const config::V1_1::ModemsConfig& modemsConfig) override;
+    Return<void> getSimSlotsStatusResponse_1_2(
+            const V1_0::RadioResponseInfo& info,
+            const hidl_vec<config::V1_2::SimSlotStatus>& slotStatus) override;
+    Return<void> getHalDeviceCapabilitiesResponse(const V1_6::RadioResponseInfo& info,
+                                                  bool modemReducedFeatureSet1) override;
+
+  public:
+    void setResponseFunction(
+            std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfigResponse> callback);
+
+    std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfigResponse> respond();
+};
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioData.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioData.h
new file mode 100644
index 0000000..c2c0de3
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioData.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include "RadioCompatBase.h"
+
+#include <aidl/android/hardware/radio/data/BnRadioData.h>
+
+namespace android::hardware::radio::compat {
+
+class RadioData : public RadioCompatBase, public aidl::android::hardware::radio::data::BnRadioData {
+    std::shared_ptr<::aidl::android::hardware::radio::data::IRadioDataResponse> respond();
+
+    ::ndk::ScopedAStatus allocatePduSessionId(int32_t serial) override;
+    ::ndk::ScopedAStatus cancelHandover(int32_t serial, int32_t callId) override;
+    ::ndk::ScopedAStatus deactivateDataCall(
+            int32_t serial, int32_t cid,
+            ::aidl::android::hardware::radio::data::DataRequestReason reason) override;
+    ::ndk::ScopedAStatus getDataCallList(int32_t serial) override;
+    ::ndk::ScopedAStatus getSlicingConfig(int32_t serial) override;
+    ::ndk::ScopedAStatus releasePduSessionId(int32_t serial, int32_t id) override;
+    ::ndk::ScopedAStatus responseAcknowledgement() override;
+    ::ndk::ScopedAStatus setDataAllowed(int32_t serial, bool allow) override;
+    ::ndk::ScopedAStatus setDataProfile(
+            int32_t serial,
+            const std::vector<::aidl::android::hardware::radio::data::DataProfileInfo>& profiles)
+            override;
+    ::ndk::ScopedAStatus setDataThrottling(
+            int32_t serial,
+            ::aidl::android::hardware::radio::data::DataThrottlingAction dataThrottlingAction,
+            int64_t completionDurationMillis) override;
+    ::ndk::ScopedAStatus setInitialAttachApn(
+            int32_t serial,
+            const std::optional<::aidl::android::hardware::radio::data::DataProfileInfo>& dpInfo)
+            override;
+    ::ndk::ScopedAStatus setResponseFunctions(
+            const std::shared_ptr<::aidl::android::hardware::radio::data::IRadioDataResponse>&
+                    radioDataResponse,
+            const std::shared_ptr<::aidl::android::hardware::radio::data::IRadioDataIndication>&
+                    radioDataIndication) override;
+    ::ndk::ScopedAStatus setupDataCall(
+            int32_t serial, ::aidl::android::hardware::radio::AccessNetwork accessNetwork,
+            const ::aidl::android::hardware::radio::data::DataProfileInfo& dataProfileInfo,
+            bool roamingAllowed, ::aidl::android::hardware::radio::data::DataRequestReason reason,
+            const std::vector<::aidl::android::hardware::radio::data::LinkAddress>& addresses,
+            const std::vector<std::string>& dnses, int32_t pduSessionId,
+            const std::optional<::aidl::android::hardware::radio::data::SliceInfo>& sliceInfo,
+            bool matchAllRuleAllowed) override;
+    ::ndk::ScopedAStatus startHandover(int32_t serial, int32_t callId) override;
+    ::ndk::ScopedAStatus startKeepalive(
+            int32_t serial,
+            const ::aidl::android::hardware::radio::data::KeepaliveRequest& keepalive) override;
+    ::ndk::ScopedAStatus stopKeepalive(int32_t serial, int32_t sessionHandle) override;
+
+  public:
+    using RadioCompatBase::RadioCompatBase;
+};
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioIndication.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioIndication.h
new file mode 100644
index 0000000..6cfd59c
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioIndication.h
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include "DriverContext.h"
+#include "GuaranteedCallback.h"
+
+#include <aidl/android/hardware/radio/data/IRadioDataIndication.h>
+#include <aidl/android/hardware/radio/messaging/IRadioMessagingIndication.h>
+#include <aidl/android/hardware/radio/modem/IRadioModemIndication.h>
+#include <aidl/android/hardware/radio/network/IRadioNetworkIndication.h>
+#include <aidl/android/hardware/radio/sim/IRadioSimIndication.h>
+#include <aidl/android/hardware/radio/voice/IRadioVoiceIndication.h>
+#include <android/hardware/radio/1.6/IRadioIndication.h>
+
+namespace android::hardware::radio::compat {
+
+class RadioIndication : public V1_6::IRadioIndication {
+    std::shared_ptr<DriverContext> mContext;
+
+    GuaranteedCallback<  //
+            ::aidl::android::hardware::radio::data::IRadioDataIndication,
+            ::aidl::android::hardware::radio::data::IRadioDataIndicationDefault, true>
+            mDataCb;
+    GuaranteedCallback<  //
+            ::aidl::android::hardware::radio::messaging::IRadioMessagingIndication,
+            ::aidl::android::hardware::radio::messaging::IRadioMessagingIndicationDefault, true>
+            mMessagingCb;
+    GuaranteedCallback<  //
+            ::aidl::android::hardware::radio::modem::IRadioModemIndication,
+            ::aidl::android::hardware::radio::modem::IRadioModemIndicationDefault, true>
+            mModemCb;
+    GuaranteedCallback<  //
+            ::aidl::android::hardware::radio::network::IRadioNetworkIndication,
+            ::aidl::android::hardware::radio::network::IRadioNetworkIndicationDefault, true>
+            mNetworkCb;
+    GuaranteedCallback<  //
+            ::aidl::android::hardware::radio::sim::IRadioSimIndication,
+            ::aidl::android::hardware::radio::sim::IRadioSimIndicationDefault, true>
+            mSimCb;
+    GuaranteedCallback<  //
+            ::aidl::android::hardware::radio::voice::IRadioVoiceIndication,
+            ::aidl::android::hardware::radio::voice::IRadioVoiceIndicationDefault, true>
+            mVoiceCb;
+
+    // IRadioIndication @ 1.0
+    Return<void> radioStateChanged(V1_0::RadioIndicationType type,
+                                   V1_0::RadioState radioState) override;
+    Return<void> callStateChanged(V1_0::RadioIndicationType type) override;
+    Return<void> networkStateChanged(V1_0::RadioIndicationType type) override;
+    Return<void> newSms(V1_0::RadioIndicationType type, const hidl_vec<uint8_t>& pdu) override;
+    Return<void> newSmsStatusReport(V1_0::RadioIndicationType type,
+                                    const hidl_vec<uint8_t>& pdu) override;
+    Return<void> newSmsOnSim(V1_0::RadioIndicationType type, int32_t recordNumber) override;
+    Return<void> onUssd(V1_0::RadioIndicationType type, V1_0::UssdModeType modeType,
+                        const hidl_string& msg) override;
+    Return<void> nitzTimeReceived(V1_0::RadioIndicationType type, const hidl_string& nitzTime,
+                                  uint64_t receivedTime) override;
+    Return<void> currentSignalStrength(V1_0::RadioIndicationType type,
+                                       const V1_0::SignalStrength& signalStrength) override;
+    Return<void> dataCallListChanged(V1_0::RadioIndicationType type,
+                                     const hidl_vec<V1_0::SetupDataCallResult>& dcList) override;
+    Return<void> suppSvcNotify(V1_0::RadioIndicationType type,
+                               const V1_0::SuppSvcNotification& suppSvc) override;
+    Return<void> stkSessionEnd(V1_0::RadioIndicationType type) override;
+    Return<void> stkProactiveCommand(V1_0::RadioIndicationType type,
+                                     const hidl_string& cmd) override;
+    Return<void> stkEventNotify(V1_0::RadioIndicationType type, const hidl_string& cmd) override;
+    Return<void> stkCallSetup(V1_0::RadioIndicationType type, int64_t timeout) override;
+    Return<void> simSmsStorageFull(V1_0::RadioIndicationType type) override;
+    Return<void> simRefresh(V1_0::RadioIndicationType type,
+                            const V1_0::SimRefreshResult& refreshResult) override;
+    Return<void> callRing(V1_0::RadioIndicationType type, bool isGsm,
+                          const V1_0::CdmaSignalInfoRecord& record) override;
+    Return<void> simStatusChanged(V1_0::RadioIndicationType type) override;
+    Return<void> cdmaNewSms(V1_0::RadioIndicationType type,
+                            const V1_0::CdmaSmsMessage& msg) override;
+    Return<void> newBroadcastSms(V1_0::RadioIndicationType type,
+                                 const hidl_vec<uint8_t>& data) override;
+    Return<void> cdmaRuimSmsStorageFull(V1_0::RadioIndicationType type) override;
+    Return<void> restrictedStateChanged(V1_0::RadioIndicationType type,
+                                        V1_0::PhoneRestrictedState state) override;
+    Return<void> enterEmergencyCallbackMode(V1_0::RadioIndicationType type) override;
+    Return<void> cdmaCallWaiting(V1_0::RadioIndicationType type,
+                                 const V1_0::CdmaCallWaiting& callWaitingRecord) override;
+    Return<void> cdmaOtaProvisionStatus(V1_0::RadioIndicationType type,
+                                        V1_0::CdmaOtaProvisionStatus status) override;
+    Return<void> cdmaInfoRec(V1_0::RadioIndicationType type,
+                             const V1_0::CdmaInformationRecords& records) override;
+    Return<void> indicateRingbackTone(V1_0::RadioIndicationType type, bool start) override;
+    Return<void> resendIncallMute(V1_0::RadioIndicationType type) override;
+    Return<void> cdmaSubscriptionSourceChanged(V1_0::RadioIndicationType type,
+                                               V1_0::CdmaSubscriptionSource cdmaSource) override;
+    Return<void> cdmaPrlChanged(V1_0::RadioIndicationType type, int32_t version) override;
+    Return<void> exitEmergencyCallbackMode(V1_0::RadioIndicationType type) override;
+    Return<void> rilConnected(V1_0::RadioIndicationType type) override;
+    Return<void> voiceRadioTechChanged(V1_0::RadioIndicationType type,
+                                       V1_0::RadioTechnology rat) override;
+    Return<void> cellInfoList(V1_0::RadioIndicationType type,
+                              const hidl_vec<V1_0::CellInfo>& records) override;
+    Return<void> imsNetworkStateChanged(V1_0::RadioIndicationType type) override;
+    Return<void> subscriptionStatusChanged(V1_0::RadioIndicationType type, bool activate) override;
+    Return<void> srvccStateNotify(V1_0::RadioIndicationType type, V1_0::SrvccState state) override;
+    Return<void> hardwareConfigChanged(V1_0::RadioIndicationType type,
+                                       const hidl_vec<V1_0::HardwareConfig>& configs) override;
+    Return<void> radioCapabilityIndication(V1_0::RadioIndicationType type,
+                                           const V1_0::RadioCapability& rc) override;
+    Return<void> onSupplementaryServiceIndication(V1_0::RadioIndicationType type,
+                                                  const V1_0::StkCcUnsolSsResult& ss) override;
+    Return<void> stkCallControlAlphaNotify(V1_0::RadioIndicationType type,
+                                           const hidl_string& alpha) override;
+    Return<void> lceData(V1_0::RadioIndicationType type, const V1_0::LceDataInfo& lce) override;
+    Return<void> pcoData(V1_0::RadioIndicationType type, const V1_0::PcoDataInfo& pco) override;
+    Return<void> modemReset(V1_0::RadioIndicationType type, const hidl_string& reason) override;
+
+    // IRadioIndication @ 1.1
+    Return<void> carrierInfoForImsiEncryption(V1_0::RadioIndicationType info) override;
+    Return<void> networkScanResult(V1_0::RadioIndicationType type,
+                                   const V1_1::NetworkScanResult& result) override;
+    Return<void> keepaliveStatus(V1_0::RadioIndicationType type,
+                                 const V1_1::KeepaliveStatus& status) override;
+
+    // IRadioIndication @ 1.2
+    Return<void> networkScanResult_1_2(V1_0::RadioIndicationType type,
+                                       const V1_2::NetworkScanResult& result) override;
+    Return<void> cellInfoList_1_2(V1_0::RadioIndicationType type,
+                                  const hidl_vec<V1_2::CellInfo>& records) override;
+    Return<void> currentLinkCapacityEstimate(V1_0::RadioIndicationType type,
+                                             const V1_2::LinkCapacityEstimate& lce) override;
+    Return<void> currentPhysicalChannelConfigs(
+            V1_0::RadioIndicationType type,
+            const hidl_vec<V1_2::PhysicalChannelConfig>& configs) override;
+    Return<void> currentSignalStrength_1_2(V1_0::RadioIndicationType type,
+                                           const V1_2::SignalStrength& signalStrength) override;
+
+    // IRadioIndication @ 1.4
+    Return<void> currentEmergencyNumberList(
+            V1_0::RadioIndicationType type,
+            const hidl_vec<V1_4::EmergencyNumber>& emergencyNumberList) override;
+    Return<void> cellInfoList_1_4(V1_0::RadioIndicationType type,
+                                  const hidl_vec<V1_4::CellInfo>& records) override;
+    Return<void> networkScanResult_1_4(V1_0::RadioIndicationType type,
+                                       const V1_4::NetworkScanResult& result) override;
+    Return<void> currentPhysicalChannelConfigs_1_4(
+            V1_0::RadioIndicationType type,
+            const hidl_vec<V1_4::PhysicalChannelConfig>& configs) override;
+    Return<void> dataCallListChanged_1_4(
+            V1_0::RadioIndicationType type,
+            const hidl_vec<V1_4::SetupDataCallResult>& dcList) override;
+    Return<void> currentSignalStrength_1_4(V1_0::RadioIndicationType type,
+                                           const V1_4::SignalStrength& signalStrength) override;
+
+    // IRadioIndication @ 1.5
+    Return<void> uiccApplicationsEnablementChanged(V1_0::RadioIndicationType type,
+                                                   bool enabled) override;
+    Return<void> registrationFailed(  //
+            V1_0::RadioIndicationType type, const V1_5::CellIdentity& cellIdentity,
+            const hidl_string& chosenPlmn, hidl_bitfield<V1_5::Domain> domain, int32_t causeCode,
+            int32_t additionalCauseCode) override;
+    Return<void> barringInfoChanged(  //
+            V1_0::RadioIndicationType type, const V1_5::CellIdentity& cellIdentity,
+            const hidl_vec<V1_5::BarringInfo>& barringInfos) override;
+    Return<void> cellInfoList_1_5(V1_0::RadioIndicationType type,
+                                  const hidl_vec<V1_5::CellInfo>& records) override;
+    Return<void> networkScanResult_1_5(V1_0::RadioIndicationType type,
+                                       const V1_5::NetworkScanResult& result) override;
+    Return<void> dataCallListChanged_1_5(
+            V1_0::RadioIndicationType type,
+            const hidl_vec<V1_5::SetupDataCallResult>& dcList) override;
+
+    // IRadioIndication @ 1.6
+    Return<void> dataCallListChanged_1_6(
+            V1_0::RadioIndicationType type,
+            const hidl_vec<V1_6::SetupDataCallResult>& dcList) override;
+    Return<void> unthrottleApn(V1_0::RadioIndicationType type, const hidl_string& apn) override;
+    Return<void> slicingConfigChanged(V1_0::RadioIndicationType type,
+                                      const V1_6::SlicingConfig& slicingConfig);
+    Return<void> currentLinkCapacityEstimate_1_6(V1_0::RadioIndicationType type,
+                                                 const V1_6::LinkCapacityEstimate& lce) override;
+    Return<void> currentSignalStrength_1_6(V1_0::RadioIndicationType type,
+                                           const V1_6::SignalStrength& signalStrength) override;
+    Return<void> cellInfoList_1_6(V1_0::RadioIndicationType type,
+                                  const hidl_vec<V1_6::CellInfo>& records) override;
+    Return<void> networkScanResult_1_6(V1_0::RadioIndicationType type,
+                                       const V1_6::NetworkScanResult& result) override;
+    Return<void> currentPhysicalChannelConfigs_1_6(
+            V1_0::RadioIndicationType type,
+            const hidl_vec<V1_6::PhysicalChannelConfig>& configs) override;
+    Return<void> simPhonebookChanged(V1_0::RadioIndicationType type) override;
+    Return<void> simPhonebookRecordsReceived(
+            V1_0::RadioIndicationType type, V1_6::PbReceivedStatus status,
+            const hidl_vec<V1_6::PhonebookRecordInfo>& records) override;
+
+  public:
+    RadioIndication(std::shared_ptr<DriverContext> context);
+
+    void setResponseFunction(
+            std::shared_ptr<::aidl::android::hardware::radio::data::IRadioDataIndication> dataCb);
+    void setResponseFunction(
+            std::shared_ptr<::aidl::android::hardware::radio::messaging::IRadioMessagingIndication>
+                    radioMessagingIndication);
+    void setResponseFunction(
+            std::shared_ptr<::aidl::android::hardware::radio::modem::IRadioModemIndication> modmCb);
+    void setResponseFunction(
+            std::shared_ptr<::aidl::android::hardware::radio::network::IRadioNetworkIndication> ni);
+    void setResponseFunction(
+            std::shared_ptr<::aidl::android::hardware::radio::sim::IRadioSimIndication> simCb);
+    void setResponseFunction(
+            std::shared_ptr<::aidl::android::hardware::radio::voice::IRadioVoiceIndication> voicCb);
+
+    std::shared_ptr<::aidl::android::hardware::radio::data::IRadioDataIndication> dataCb();
+    std::shared_ptr<::aidl::android::hardware::radio::messaging::IRadioMessagingIndication>
+    messagingCb();
+    std::shared_ptr<::aidl::android::hardware::radio::modem::IRadioModemIndication> modemCb();
+    std::shared_ptr<::aidl::android::hardware::radio::network::IRadioNetworkIndication> networkCb();
+    std::shared_ptr<::aidl::android::hardware::radio::sim::IRadioSimIndication> simCb();
+    std::shared_ptr<::aidl::android::hardware::radio::voice::IRadioVoiceIndication> voiceCb();
+};
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioMessaging.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioMessaging.h
new file mode 100644
index 0000000..047f836
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioMessaging.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include "RadioCompatBase.h"
+
+#include <aidl/android/hardware/radio/messaging/BnRadioMessaging.h>
+
+namespace android::hardware::radio::compat {
+
+class RadioMessaging : public RadioCompatBase,
+                       public aidl::android::hardware::radio::messaging::BnRadioMessaging {
+    std::shared_ptr<::aidl::android::hardware::radio::messaging::IRadioMessagingResponse> respond();
+
+    ::ndk::ScopedAStatus acknowledgeIncomingGsmSmsWithPdu(int32_t serial, bool success,
+                                                          const std::string& ackPdu) override;
+    ::ndk::ScopedAStatus acknowledgeLastIncomingCdmaSms(
+            int32_t serial,
+            const ::aidl::android::hardware::radio::messaging::CdmaSmsAck& smsAck) override;
+    ::ndk::ScopedAStatus acknowledgeLastIncomingGsmSms(
+            int32_t serial, bool success,
+            ::aidl::android::hardware::radio::messaging::SmsAcknowledgeFailCause cause) override;
+    ::ndk::ScopedAStatus deleteSmsOnRuim(int32_t serial, int32_t index) override;
+    ::ndk::ScopedAStatus deleteSmsOnSim(int32_t serial, int32_t index) override;
+    ::ndk::ScopedAStatus getCdmaBroadcastConfig(int32_t serial) override;
+    ::ndk::ScopedAStatus getGsmBroadcastConfig(int32_t serial) override;
+    ::ndk::ScopedAStatus getSmscAddress(int32_t serial) override;
+    ::ndk::ScopedAStatus reportSmsMemoryStatus(int32_t serial, bool available) override;
+    ::ndk::ScopedAStatus responseAcknowledgement() override;
+    ::ndk::ScopedAStatus sendCdmaSms(
+            int32_t serial,
+            const ::aidl::android::hardware::radio::messaging::CdmaSmsMessage& sms) override;
+    ::ndk::ScopedAStatus sendCdmaSmsExpectMore(
+            int32_t serial,
+            const ::aidl::android::hardware::radio::messaging::CdmaSmsMessage& sms) override;
+    ::ndk::ScopedAStatus sendImsSms(
+            int32_t serial,
+            const ::aidl::android::hardware::radio::messaging::ImsSmsMessage& message) override;
+    ::ndk::ScopedAStatus sendSms(
+            int32_t serial,
+            const ::aidl::android::hardware::radio::messaging::GsmSmsMessage& message) override;
+    ::ndk::ScopedAStatus sendSmsExpectMore(
+            int32_t serial,
+            const ::aidl::android::hardware::radio::messaging::GsmSmsMessage& message) override;
+    ::ndk::ScopedAStatus setCdmaBroadcastActivation(int32_t serial, bool activate) override;
+    ::ndk::ScopedAStatus setCdmaBroadcastConfig(
+            int32_t serial,
+            const std::vector<
+                    ::aidl::android::hardware::radio::messaging::CdmaBroadcastSmsConfigInfo>&
+                    configInfo) override;
+    ::ndk::ScopedAStatus setGsmBroadcastActivation(int32_t serial, bool activate) override;
+    ::ndk::ScopedAStatus setGsmBroadcastConfig(
+            int32_t serial,
+            const std::vector<
+                    ::aidl::android::hardware::radio::messaging::GsmBroadcastSmsConfigInfo>&
+                    configInfo) override;
+    ::ndk::ScopedAStatus setResponseFunctions(
+            const std::shared_ptr<
+                    ::aidl::android::hardware::radio::messaging::IRadioMessagingResponse>&
+                    radioMessagingResponse,
+            const std::shared_ptr<
+                    ::aidl::android::hardware::radio::messaging::IRadioMessagingIndication>&
+                    radioMessagingIndication) override;
+    ::ndk::ScopedAStatus setSmscAddress(int32_t serial, const std::string& smsc) override;
+    ::ndk::ScopedAStatus writeSmsToRuim(
+            int32_t serial,
+            const ::aidl::android::hardware::radio::messaging::CdmaSmsWriteArgs& cdmaSms) override;
+    ::ndk::ScopedAStatus writeSmsToSim(
+            int32_t serial,
+            const ::aidl::android::hardware::radio::messaging::SmsWriteArgs& smsWriteArgs) override;
+
+  public:
+    using RadioCompatBase::RadioCompatBase;
+};
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioModem.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioModem.h
new file mode 100644
index 0000000..fdca124
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioModem.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include "RadioCompatBase.h"
+
+#include <aidl/android/hardware/radio/modem/BnRadioModem.h>
+
+namespace android::hardware::radio::compat {
+
+class RadioModem : public RadioCompatBase,
+                   public aidl::android::hardware::radio::modem::BnRadioModem {
+    std::shared_ptr<::aidl::android::hardware::radio::modem::IRadioModemResponse> respond();
+
+    ::ndk::ScopedAStatus enableModem(int32_t serial, bool on) override;
+    ::ndk::ScopedAStatus getBasebandVersion(int32_t serial) override;
+    ::ndk::ScopedAStatus getDeviceIdentity(int32_t serial) override;
+    ::ndk::ScopedAStatus getHardwareConfig(int32_t serial) override;
+    ::ndk::ScopedAStatus getModemActivityInfo(int32_t serial) override;
+    ::ndk::ScopedAStatus getModemStackStatus(int32_t serial) override;
+    ::ndk::ScopedAStatus getRadioCapability(int32_t serial) override;
+    ::ndk::ScopedAStatus nvReadItem(
+            int32_t serial, ::aidl::android::hardware::radio::modem::NvItem itemId) override;
+    ::ndk::ScopedAStatus nvResetConfig(
+            int32_t serial, ::aidl::android::hardware::radio::modem::ResetNvType type) override;
+    ::ndk::ScopedAStatus nvWriteCdmaPrl(int32_t serial, const std::vector<uint8_t>& prl) override;
+    ::ndk::ScopedAStatus nvWriteItem(
+            int32_t serial, const ::aidl::android::hardware::radio::modem::NvWriteItem& i) override;
+    ::ndk::ScopedAStatus requestShutdown(int32_t serial) override;
+    ::ndk::ScopedAStatus responseAcknowledgement() override;
+    ::ndk::ScopedAStatus sendDeviceState(
+            int32_t serial, ::aidl::android::hardware::radio::modem::DeviceStateType stateType,
+            bool state) override;
+    ::ndk::ScopedAStatus setRadioCapability(
+            int32_t s, const ::aidl::android::hardware::radio::modem::RadioCapability& rc) override;
+    ::ndk::ScopedAStatus setRadioPower(int32_t serial, bool powerOn, bool forEmergencyCall,
+                                       bool preferredForEmergencyCall) override;
+    ::ndk::ScopedAStatus setResponseFunctions(
+            const std::shared_ptr<::aidl::android::hardware::radio::modem::IRadioModemResponse>&
+                    radioModemResponse,
+            const std::shared_ptr<::aidl::android::hardware::radio::modem::IRadioModemIndication>&
+                    radioModemIndication) override;
+
+  public:
+    using RadioCompatBase::RadioCompatBase;
+};
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h
new file mode 100644
index 0000000..1731b78
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include "RadioCompatBase.h"
+
+#include <aidl/android/hardware/radio/network/BnRadioNetwork.h>
+
+namespace android::hardware::radio::compat {
+
+class RadioNetwork : public RadioCompatBase,
+                     public aidl::android::hardware::radio::network::BnRadioNetwork {
+    std::shared_ptr<::aidl::android::hardware::radio::network::IRadioNetworkResponse> respond();
+
+    ::ndk::ScopedAStatus getAllowedNetworkTypesBitmap(int32_t serial) override;
+    ::ndk::ScopedAStatus getAvailableBandModes(int32_t serial) override;
+    ::ndk::ScopedAStatus getAvailableNetworks(int32_t serial) override;
+    ::ndk::ScopedAStatus getBarringInfo(int32_t serial) override;
+    ::ndk::ScopedAStatus getCdmaRoamingPreference(int32_t serial) override;
+    ::ndk::ScopedAStatus getCellInfoList(int32_t serial) override;
+    ::ndk::ScopedAStatus getDataRegistrationState(int32_t serial) override;
+    ::ndk::ScopedAStatus getImsRegistrationState(int32_t serial) override;
+    ::ndk::ScopedAStatus getNetworkSelectionMode(int32_t serial) override;
+    ::ndk::ScopedAStatus getOperator(int32_t serial) override;
+    ::ndk::ScopedAStatus getSignalStrength(int32_t serial) override;
+    ::ndk::ScopedAStatus getSystemSelectionChannels(int32_t serial) override;
+    ::ndk::ScopedAStatus getVoiceRadioTechnology(int32_t serial) override;
+    ::ndk::ScopedAStatus getVoiceRegistrationState(int32_t serial) override;
+    ::ndk::ScopedAStatus isNrDualConnectivityEnabled(int32_t serial) override;
+    ::ndk::ScopedAStatus responseAcknowledgement() override;
+    ::ndk::ScopedAStatus setAllowedNetworkTypesBitmap(int32_t serial,
+                                                      int32_t networkTypeBitmap) override;
+    ::ndk::ScopedAStatus setBandMode(
+            int32_t serial, ::aidl::android::hardware::radio::network::RadioBandMode mode) override;
+    ::ndk::ScopedAStatus setBarringPassword(int32_t serial, const std::string& facility,
+                                            const std::string& oldPassword,
+                                            const std::string& newPassword) override;
+    ::ndk::ScopedAStatus setCdmaRoamingPreference(
+            int32_t serial,
+            ::aidl::android::hardware::radio::network::CdmaRoamingType type) override;
+    ::ndk::ScopedAStatus setCellInfoListRate(int32_t serial, int32_t rate) override;
+    ::ndk::ScopedAStatus setIndicationFilter(int32_t serial, int32_t indicationFilter) override;
+    ::ndk::ScopedAStatus setLinkCapacityReportingCriteria(
+            int32_t serial, int32_t hysteresisMs, int32_t hysteresisDlKbps,
+            int32_t hysteresisUlKbps, const std::vector<int32_t>& thresholdsDownlinkKbps,
+            const std::vector<int32_t>& thresholdsUplinkKbps,
+            ::aidl::android::hardware::radio::AccessNetwork accessNetwork) override;
+    ::ndk::ScopedAStatus setLocationUpdates(int32_t serial, bool enable) override;
+    ::ndk::ScopedAStatus setNetworkSelectionModeAutomatic(int32_t serial) override;
+    ::ndk::ScopedAStatus setNetworkSelectionModeManual(
+            int32_t serial, const std::string& operatorNumeric,
+            ::aidl::android::hardware::radio::AccessNetwork ran) override;
+    ::ndk::ScopedAStatus setNrDualConnectivityState(
+            int32_t serial,
+            ::aidl::android::hardware::radio::network::NrDualConnectivityState nrSt) override;
+    ::ndk::ScopedAStatus setResponseFunctions(
+            const std::shared_ptr<::aidl::android::hardware::radio::network::IRadioNetworkResponse>&
+                    radioNetworkResponse,
+            const std::shared_ptr<
+                    ::aidl::android::hardware::radio::network::IRadioNetworkIndication>&
+                    radioNetworkIndication) override;
+    ::ndk::ScopedAStatus setSignalStrengthReportingCriteria(
+            int32_t serial,
+            const std::vector<::aidl::android::hardware::radio::network::SignalThresholdInfo>&
+                    signalThresholdInfos) override;
+    ::ndk::ScopedAStatus setSuppServiceNotifications(int32_t serial, bool enable) override;
+    ::ndk::ScopedAStatus setSystemSelectionChannels(
+            int32_t serial, bool specifyChannels,
+            const std::vector<::aidl::android::hardware::radio::network::RadioAccessSpecifier>&
+                    specifiers) override;
+    ::ndk::ScopedAStatus startNetworkScan(
+            int32_t serial,
+            const ::aidl::android::hardware::radio::network::NetworkScanRequest& request) override;
+    ::ndk::ScopedAStatus stopNetworkScan(int32_t serial) override;
+    ::ndk::ScopedAStatus supplyNetworkDepersonalization(int32_t serial,
+                                                        const std::string& netPin) override;
+    ::ndk::ScopedAStatus setUsageSetting(
+            int32_t serial,
+            ::aidl::android::hardware::radio::network::UsageSetting usageSetting) override;
+    ::ndk::ScopedAStatus getUsageSetting(int32_t serial) override;
+
+  public:
+    using RadioCompatBase::RadioCompatBase;
+};
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioResponse.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioResponse.h
new file mode 100644
index 0000000..1f82dd1
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioResponse.h
@@ -0,0 +1,453 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include "DriverContext.h"
+#include "GuaranteedCallback.h"
+
+#include <aidl/android/hardware/radio/data/IRadioDataResponse.h>
+#include <aidl/android/hardware/radio/messaging/IRadioMessagingResponse.h>
+#include <aidl/android/hardware/radio/modem/IRadioModemResponse.h>
+#include <aidl/android/hardware/radio/network/IRadioNetworkResponse.h>
+#include <aidl/android/hardware/radio/sim/IRadioSimResponse.h>
+#include <aidl/android/hardware/radio/voice/IRadioVoiceResponse.h>
+#include <android/hardware/radio/1.6/IRadioResponse.h>
+
+namespace android::hardware::radio::compat {
+
+class RadioResponse : public V1_6::IRadioResponse {
+    std::shared_ptr<DriverContext> mContext;
+
+    GuaranteedCallback<::aidl::android::hardware::radio::data::IRadioDataResponse,
+                       ::aidl::android::hardware::radio::data::IRadioDataResponseDefault>
+            mDataCb;
+    GuaranteedCallback<::aidl::android::hardware::radio::messaging::IRadioMessagingResponse,
+                       ::aidl::android::hardware::radio::messaging::IRadioMessagingResponseDefault>
+            mMessagingCb;
+    GuaranteedCallback<::aidl::android::hardware::radio::modem::IRadioModemResponse,
+                       ::aidl::android::hardware::radio::modem::IRadioModemResponseDefault>
+            mModemCb;
+    GuaranteedCallback<::aidl::android::hardware::radio::network::IRadioNetworkResponse,
+                       ::aidl::android::hardware::radio::network::IRadioNetworkResponseDefault>
+            mNetworkCb;
+    GuaranteedCallback<::aidl::android::hardware::radio::sim::IRadioSimResponse,
+                       ::aidl::android::hardware::radio::sim::IRadioSimResponseDefault>
+            mSimCb;
+    GuaranteedCallback<::aidl::android::hardware::radio::voice::IRadioVoiceResponse,
+                       ::aidl::android::hardware::radio::voice::IRadioVoiceResponseDefault>
+            mVoiceCb;
+
+    // IRadioResponse @ 1.0
+    Return<void> getIccCardStatusResponse(const V1_0::RadioResponseInfo& info,
+                                          const V1_0::CardStatus& cardStatus) override;
+    Return<void> supplyIccPinForAppResponse(const V1_0::RadioResponseInfo& info,
+                                            int32_t remainingRetries) override;
+    Return<void> supplyIccPukForAppResponse(const V1_0::RadioResponseInfo& info,
+                                            int32_t remainingRetries) override;
+    Return<void> supplyIccPin2ForAppResponse(const V1_0::RadioResponseInfo& info,
+                                             int32_t remainingRetries) override;
+    Return<void> supplyIccPuk2ForAppResponse(const V1_0::RadioResponseInfo& info,
+                                             int32_t remainingRetries) override;
+    Return<void> changeIccPinForAppResponse(const V1_0::RadioResponseInfo& info,
+                                            int32_t remainingRetries) override;
+    Return<void> changeIccPin2ForAppResponse(const V1_0::RadioResponseInfo& info,
+                                             int32_t remainingRetries) override;
+    Return<void> supplyNetworkDepersonalizationResponse(const V1_0::RadioResponseInfo& info,
+                                                        int32_t remainingRetries) override;
+    Return<void> getCurrentCallsResponse(const V1_0::RadioResponseInfo& info,
+                                         const hidl_vec<V1_0::Call>& calls) override;
+    Return<void> dialResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> getIMSIForAppResponse(const V1_0::RadioResponseInfo& info,
+                                       const hidl_string& imsi) override;
+    Return<void> hangupConnectionResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> hangupWaitingOrBackgroundResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> hangupForegroundResumeBackgroundResponse(
+            const V1_0::RadioResponseInfo& info) override;
+    Return<void> switchWaitingOrHoldingAndActiveResponse(
+            const V1_0::RadioResponseInfo& info) override;
+    Return<void> conferenceResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> rejectCallResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> getLastCallFailCauseResponse(
+            const V1_0::RadioResponseInfo& info,
+            const V1_0::LastCallFailCauseInfo& failCauseinfo) override;
+    Return<void> getSignalStrengthResponse(const V1_0::RadioResponseInfo& info,
+                                           const V1_0::SignalStrength& sigStrength) override;
+    Return<void> getVoiceRegistrationStateResponse(
+            const V1_0::RadioResponseInfo& info,
+            const V1_0::VoiceRegStateResult& voiceRegResponse) override;
+    Return<void> getDataRegistrationStateResponse(
+            const V1_0::RadioResponseInfo& info,
+            const V1_0::DataRegStateResult& dataRegResponse) override;
+    Return<void> getOperatorResponse(const V1_0::RadioResponseInfo& info,
+                                     const hidl_string& longName, const hidl_string& shortName,
+                                     const hidl_string& numeric) override;
+    Return<void> setRadioPowerResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> sendDtmfResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> sendSmsResponse(const V1_0::RadioResponseInfo& info,
+                                 const V1_0::SendSmsResult& sms) override;
+    Return<void> sendSMSExpectMoreResponse(const V1_0::RadioResponseInfo& info,
+                                           const V1_0::SendSmsResult& sms) override;
+    Return<void> setupDataCallResponse(const V1_0::RadioResponseInfo& info,
+                                       const V1_0::SetupDataCallResult& dcResponse) override;
+    Return<void> iccIOForAppResponse(const V1_0::RadioResponseInfo& info,
+                                     const V1_0::IccIoResult& iccIo) override;
+    Return<void> sendUssdResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> cancelPendingUssdResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> getClirResponse(const V1_0::RadioResponseInfo& info, int32_t n,
+                                 int32_t m) override;
+    Return<void> setClirResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> getCallForwardStatusResponse(
+            const V1_0::RadioResponseInfo& info,
+            const hidl_vec<V1_0::CallForwardInfo>& callForwardInfos) override;
+    Return<void> setCallForwardResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> getCallWaitingResponse(const V1_0::RadioResponseInfo& info, bool enable,
+                                        int32_t serviceClass) override;
+    Return<void> setCallWaitingResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> acknowledgeLastIncomingGsmSmsResponse(
+            const V1_0::RadioResponseInfo& info) override;
+    Return<void> acceptCallResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> deactivateDataCallResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> getFacilityLockForAppResponse(const V1_0::RadioResponseInfo& info,
+                                               int32_t response) override;
+    Return<void> setFacilityLockForAppResponse(const V1_0::RadioResponseInfo& info,
+                                               int32_t retry) override;
+    Return<void> setBarringPasswordResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> getNetworkSelectionModeResponse(const V1_0::RadioResponseInfo& info,
+                                                 bool manual) override;
+    Return<void> setNetworkSelectionModeAutomaticResponse(
+            const V1_0::RadioResponseInfo& info) override;
+    Return<void> setNetworkSelectionModeManualResponse(
+            const V1_0::RadioResponseInfo& info) override;
+    Return<void> getAvailableNetworksResponse(
+            const V1_0::RadioResponseInfo& info,
+            const hidl_vec<V1_0::OperatorInfo>& networkInfos) override;
+    Return<void> startDtmfResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> stopDtmfResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> getBasebandVersionResponse(const V1_0::RadioResponseInfo& info,
+                                            const hidl_string& version) override;
+    Return<void> separateConnectionResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> setMuteResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> getMuteResponse(const V1_0::RadioResponseInfo& info, bool enable) override;
+    Return<void> getClipResponse(const V1_0::RadioResponseInfo& info,
+                                 V1_0::ClipStatus status) override;
+    Return<void> getDataCallListResponse(
+            const V1_0::RadioResponseInfo& info,
+            const hidl_vec<V1_0::SetupDataCallResult>& dcResponse) override;
+    Return<void> setSuppServiceNotificationsResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> writeSmsToSimResponse(const V1_0::RadioResponseInfo& info, int32_t index) override;
+    Return<void> deleteSmsOnSimResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> setBandModeResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> getAvailableBandModesResponse(
+            const V1_0::RadioResponseInfo& info,
+            const hidl_vec<V1_0::RadioBandMode>& bandModes) override;
+    Return<void> sendEnvelopeResponse(const V1_0::RadioResponseInfo& info,
+                                      const hidl_string& commandResponse) override;
+    Return<void> sendTerminalResponseToSimResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> handleStkCallSetupRequestFromSimResponse(
+            const V1_0::RadioResponseInfo& info) override;
+    Return<void> explicitCallTransferResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> setPreferredNetworkTypeResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> getPreferredNetworkTypeResponse(const V1_0::RadioResponseInfo& info,
+                                                 V1_0::PreferredNetworkType nwType) override;
+    Return<void> getNeighboringCidsResponse(const V1_0::RadioResponseInfo& info,
+                                            const hidl_vec<V1_0::NeighboringCell>& cells) override;
+    Return<void> setLocationUpdatesResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> setCdmaSubscriptionSourceResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> setCdmaRoamingPreferenceResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> getCdmaRoamingPreferenceResponse(const V1_0::RadioResponseInfo& info,
+                                                  V1_0::CdmaRoamingType type) override;
+    Return<void> setTTYModeResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> getTTYModeResponse(const V1_0::RadioResponseInfo& info,
+                                    V1_0::TtyMode mode) override;
+    Return<void> setPreferredVoicePrivacyResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> getPreferredVoicePrivacyResponse(const V1_0::RadioResponseInfo& info,
+                                                  bool enable) override;
+    Return<void> sendCDMAFeatureCodeResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> sendBurstDtmfResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> sendCdmaSmsResponse(const V1_0::RadioResponseInfo& info,
+                                     const V1_0::SendSmsResult& sms) override;
+    Return<void> acknowledgeLastIncomingCdmaSmsResponse(
+            const V1_0::RadioResponseInfo& info) override;
+    Return<void> getGsmBroadcastConfigResponse(
+            const V1_0::RadioResponseInfo& info,
+            const hidl_vec<V1_0::GsmBroadcastSmsConfigInfo>& configs) override;
+    Return<void> setGsmBroadcastConfigResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> setGsmBroadcastActivationResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> getCdmaBroadcastConfigResponse(
+            const V1_0::RadioResponseInfo& info,
+            const hidl_vec<V1_0::CdmaBroadcastSmsConfigInfo>& configs) override;
+    Return<void> setCdmaBroadcastConfigResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> setCdmaBroadcastActivationResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> getCDMASubscriptionResponse(  //
+            const V1_0::RadioResponseInfo& info, const hidl_string& mdn, const hidl_string& hSid,
+            const hidl_string& hNid, const hidl_string& min, const hidl_string& prl) override;
+    Return<void> writeSmsToRuimResponse(const V1_0::RadioResponseInfo& info,
+                                        uint32_t index) override;
+    Return<void> deleteSmsOnRuimResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> getDeviceIdentityResponse(  //
+            const V1_0::RadioResponseInfo& info, const hidl_string& imei, const hidl_string& imeisv,
+            const hidl_string& esn, const hidl_string& meid) override;
+    Return<void> exitEmergencyCallbackModeResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> getSmscAddressResponse(const V1_0::RadioResponseInfo& info,
+                                        const hidl_string& smsc) override;
+    Return<void> setSmscAddressResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> reportSmsMemoryStatusResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> reportStkServiceIsRunningResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> getCdmaSubscriptionSourceResponse(const V1_0::RadioResponseInfo& info,
+                                                   V1_0::CdmaSubscriptionSource source) override;
+    Return<void> requestIsimAuthenticationResponse(const V1_0::RadioResponseInfo& info,
+                                                   const hidl_string& response) override;
+    Return<void> acknowledgeIncomingGsmSmsWithPduResponse(
+            const V1_0::RadioResponseInfo& info) override;
+    Return<void> sendEnvelopeWithStatusResponse(const V1_0::RadioResponseInfo& info,
+                                                const V1_0::IccIoResult& iccIo) override;
+    Return<void> getVoiceRadioTechnologyResponse(const V1_0::RadioResponseInfo& info,
+                                                 V1_0::RadioTechnology rat) override;
+    Return<void> getCellInfoListResponse(const V1_0::RadioResponseInfo& info,
+                                         const hidl_vec<V1_0::CellInfo>& cellInfo) override;
+    Return<void> setCellInfoListRateResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> setInitialAttachApnResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> getImsRegistrationStateResponse(const V1_0::RadioResponseInfo& info,
+                                                 bool isRegistered,
+                                                 V1_0::RadioTechnologyFamily ratFamily) override;
+    Return<void> sendImsSmsResponse(const V1_0::RadioResponseInfo& info,
+                                    const V1_0::SendSmsResult& sms) override;
+    Return<void> iccTransmitApduBasicChannelResponse(const V1_0::RadioResponseInfo& info,
+                                                     const V1_0::IccIoResult& result) override;
+    Return<void> iccOpenLogicalChannelResponse(const V1_0::RadioResponseInfo& info,
+                                               int32_t channelId,
+                                               const hidl_vec<int8_t>& selectResponse) override;
+    Return<void> iccCloseLogicalChannelResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> iccTransmitApduLogicalChannelResponse(const V1_0::RadioResponseInfo& info,
+                                                       const V1_0::IccIoResult& result) override;
+    Return<void> nvReadItemResponse(const V1_0::RadioResponseInfo& info,
+                                    const hidl_string& result) override;
+    Return<void> nvWriteItemResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> nvWriteCdmaPrlResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> nvResetConfigResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> setUiccSubscriptionResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> setDataAllowedResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> getHardwareConfigResponse(const V1_0::RadioResponseInfo& info,
+                                           const hidl_vec<V1_0::HardwareConfig>& config) override;
+    Return<void> requestIccSimAuthenticationResponse(const V1_0::RadioResponseInfo& info,
+                                                     const V1_0::IccIoResult& result) override;
+    Return<void> setDataProfileResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> requestShutdownResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> getRadioCapabilityResponse(const V1_0::RadioResponseInfo& info,
+                                            const V1_0::RadioCapability& rc) override;
+    Return<void> setRadioCapabilityResponse(const V1_0::RadioResponseInfo& info,
+                                            const V1_0::RadioCapability& rc) override;
+    Return<void> startLceServiceResponse(const V1_0::RadioResponseInfo& info,
+                                         const V1_0::LceStatusInfo& statusInfo) override;
+    Return<void> stopLceServiceResponse(const V1_0::RadioResponseInfo& info,
+                                        const V1_0::LceStatusInfo& statusInfo) override;
+    Return<void> pullLceDataResponse(const V1_0::RadioResponseInfo& info,
+                                     const V1_0::LceDataInfo& lceInfo) override;
+    Return<void> getModemActivityInfoResponse(const V1_0::RadioResponseInfo& info,
+                                              const V1_0::ActivityStatsInfo& activityInfo) override;
+    Return<void> setAllowedCarriersResponse(const V1_0::RadioResponseInfo& info,
+                                            int32_t numAllowed) override;
+    Return<void> getAllowedCarriersResponse(const V1_0::RadioResponseInfo& info, bool allAllowed,
+                                            const V1_0::CarrierRestrictions& carriers) override;
+    Return<void> sendDeviceStateResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> setIndicationFilterResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> setSimCardPowerResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> acknowledgeRequest(int32_t serial) override;
+
+    // IRadioResponse @ 1.1
+    Return<void> setCarrierInfoForImsiEncryptionResponse(
+            const V1_0::RadioResponseInfo& info) override;
+    Return<void> setSimCardPowerResponse_1_1(const V1_0::RadioResponseInfo& info) override;
+    Return<void> startNetworkScanResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> stopNetworkScanResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> startKeepaliveResponse(const V1_0::RadioResponseInfo& info,
+                                        const V1_1::KeepaliveStatus& status) override;
+    Return<void> stopKeepaliveResponse(const V1_0::RadioResponseInfo& info) override;
+
+    // IRadioResponse @ 1.2
+    Return<void> getCellInfoListResponse_1_2(const V1_0::RadioResponseInfo& info,
+                                             const hidl_vec<V1_2::CellInfo>& cellInfo) override;
+    Return<void> getIccCardStatusResponse_1_2(const V1_0::RadioResponseInfo& info,
+                                              const V1_2::CardStatus& cardStatus) override;
+    Return<void> setSignalStrengthReportingCriteriaResponse(
+            const V1_0::RadioResponseInfo& info) override;
+    Return<void> setLinkCapacityReportingCriteriaResponse(
+            const V1_0::RadioResponseInfo& info) override;
+    Return<void> getCurrentCallsResponse_1_2(const V1_0::RadioResponseInfo& info,
+                                             const hidl_vec<V1_2::Call>& calls) override;
+    Return<void> getSignalStrengthResponse_1_2(const V1_0::RadioResponseInfo& info,
+                                               const V1_2::SignalStrength& signalStrength) override;
+    Return<void> getVoiceRegistrationStateResponse_1_2(
+            const V1_0::RadioResponseInfo& info,
+            const V1_2::VoiceRegStateResult& voiceRegResponse) override;
+    Return<void> getDataRegistrationStateResponse_1_2(
+            const V1_0::RadioResponseInfo& info,
+            const V1_2::DataRegStateResult& dataRegResponse) override;
+
+    // IRadioResponse @ 1.3
+    Return<void> setSystemSelectionChannelsResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> enableModemResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> getModemStackStatusResponse(const V1_0::RadioResponseInfo& info,
+                                             bool isEnabled) override;
+
+    // IRadioResponse @ 1.4
+    Return<void> emergencyDialResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> startNetworkScanResponse_1_4(const V1_0::RadioResponseInfo& info) override;
+    Return<void> getCellInfoListResponse_1_4(const V1_0::RadioResponseInfo& info,
+                                             const hidl_vec<V1_4::CellInfo>& cellInfo) override;
+    Return<void> getDataRegistrationStateResponse_1_4(
+            const V1_0::RadioResponseInfo& info,
+            const V1_4::DataRegStateResult& dataRegResponse) override;
+    Return<void> getIccCardStatusResponse_1_4(const V1_0::RadioResponseInfo& info,
+                                              const V1_4::CardStatus& cardStatus) override;
+    Return<void> getPreferredNetworkTypeBitmapResponse(
+            const V1_0::RadioResponseInfo& info,
+            hidl_bitfield<V1_4::RadioAccessFamily> networkTypeBitmap) override;
+    Return<void> setPreferredNetworkTypeBitmapResponse(
+            const V1_0::RadioResponseInfo& info) override;
+    Return<void> getDataCallListResponse_1_4(
+            const V1_0::RadioResponseInfo& info,
+            const hidl_vec<V1_4::SetupDataCallResult>& dcResponse) override;
+    Return<void> setupDataCallResponse_1_4(const V1_0::RadioResponseInfo& info,
+                                           const V1_4::SetupDataCallResult& dcResponse) override;
+    Return<void> setAllowedCarriersResponse_1_4(const V1_0::RadioResponseInfo& info) override;
+    Return<void> getAllowedCarriersResponse_1_4(
+            const V1_0::RadioResponseInfo& info,
+            const V1_4::CarrierRestrictionsWithPriority& carriers,
+            V1_4::SimLockMultiSimPolicy multiSimPolicy) override;
+    Return<void> getSignalStrengthResponse_1_4(const V1_0::RadioResponseInfo& info,
+                                               const V1_4::SignalStrength& signalStrength) override;
+
+    // IRadioResponse @ 1.5
+    Return<void> setSignalStrengthReportingCriteriaResponse_1_5(
+            const V1_0::RadioResponseInfo& info) override;
+    Return<void> setLinkCapacityReportingCriteriaResponse_1_5(
+            const V1_0::RadioResponseInfo& info) override;
+    Return<void> enableUiccApplicationsResponse(const V1_0::RadioResponseInfo& info) override;
+    Return<void> areUiccApplicationsEnabledResponse(const V1_0::RadioResponseInfo& info,
+                                                    bool enabled) override;
+    Return<void> setSystemSelectionChannelsResponse_1_5(
+            const V1_0::RadioResponseInfo& info) override;
+    Return<void> startNetworkScanResponse_1_5(const V1_0::RadioResponseInfo& info) override;
+    Return<void> setupDataCallResponse_1_5(const V1_0::RadioResponseInfo& info,
+                                           const V1_5::SetupDataCallResult& dcResponse) override;
+    Return<void> getDataCallListResponse_1_5(
+            const V1_0::RadioResponseInfo& info,
+            const hidl_vec<V1_5::SetupDataCallResult>& dcResponse) override;
+    Return<void> setInitialAttachApnResponse_1_5(const V1_0::RadioResponseInfo& info) override;
+    Return<void> setDataProfileResponse_1_5(const V1_0::RadioResponseInfo& info) override;
+    Return<void> setRadioPowerResponse_1_5(const V1_0::RadioResponseInfo& info) override;
+    Return<void> setIndicationFilterResponse_1_5(const V1_0::RadioResponseInfo& info) override;
+    Return<void> getBarringInfoResponse(const V1_0::RadioResponseInfo& info,
+                                        const V1_5::CellIdentity& cellIdentity,
+                                        const hidl_vec<V1_5::BarringInfo>& barringInfos) override;
+    Return<void> getVoiceRegistrationStateResponse_1_5(
+            const V1_0::RadioResponseInfo& info,
+            const V1_5::RegStateResult& voiceRegResponse) override;
+    Return<void> getDataRegistrationStateResponse_1_5(
+            const V1_0::RadioResponseInfo& info,
+            const V1_5::RegStateResult& dataRegResponse) override;
+    Return<void> getCellInfoListResponse_1_5(const V1_0::RadioResponseInfo& info,
+                                             const hidl_vec<V1_5::CellInfo>& cellInfo) override;
+    Return<void> setNetworkSelectionModeManualResponse_1_5(
+            const V1_0::RadioResponseInfo& info) override;
+    Return<void> sendCdmaSmsExpectMoreResponse(const V1_0::RadioResponseInfo& info,
+                                               const V1_0::SendSmsResult& sms) override;
+    Return<void> supplySimDepersonalizationResponse(const V1_0::RadioResponseInfo& info,
+                                                    V1_5::PersoSubstate persoType,
+                                                    int32_t remainingRetries) override;
+    Return<void> getIccCardStatusResponse_1_5(const V1_0::RadioResponseInfo& info,
+                                              const V1_5::CardStatus& cardStatus) override;
+
+    // IRadioResponse @ 1.6
+    Return<void> setRadioPowerResponse_1_6(const V1_6::RadioResponseInfo& info) override;
+    Return<void> setupDataCallResponse_1_6(const V1_6::RadioResponseInfo& info,
+                                           const V1_6::SetupDataCallResult& dcResponse) override;
+    Return<void> getDataCallListResponse_1_6(
+            const V1_6::RadioResponseInfo& info,
+            const hidl_vec<V1_6::SetupDataCallResult>& dcResponse) override;
+    Return<void> sendSmsResponse_1_6(const V1_6::RadioResponseInfo& info,
+                                     const V1_0::SendSmsResult& sms) override;
+    Return<void> sendSmsExpectMoreResponse_1_6(const V1_6::RadioResponseInfo& info,
+                                               const V1_0::SendSmsResult& sms) override;
+    Return<void> sendCdmaSmsResponse_1_6(const V1_6::RadioResponseInfo& info,
+                                         const V1_0::SendSmsResult& sms) override;
+    Return<void> sendCdmaSmsExpectMoreResponse_1_6(const V1_6::RadioResponseInfo& info,
+                                                   const V1_0::SendSmsResult& sms) override;
+    Return<void> setSimCardPowerResponse_1_6(const V1_6::RadioResponseInfo& info) override;
+    Return<void> setNrDualConnectivityStateResponse(const V1_6::RadioResponseInfo& info) override;
+    Return<void> isNrDualConnectivityEnabledResponse(const V1_6::RadioResponseInfo& info,
+                                                     bool isEnabled) override;
+    Return<void> allocatePduSessionIdResponse(const V1_6::RadioResponseInfo& info,
+                                              int32_t id) override;
+    Return<void> releasePduSessionIdResponse(const V1_6::RadioResponseInfo& info) override;
+    Return<void> startHandoverResponse(const V1_6::RadioResponseInfo& info) override;
+    Return<void> cancelHandoverResponse(const V1_6::RadioResponseInfo& info) override;
+    Return<void> setAllowedNetworkTypesBitmapResponse(const V1_6::RadioResponseInfo& info) override;
+    Return<void> getAllowedNetworkTypesBitmapResponse(
+            const V1_6::RadioResponseInfo& info,
+            hidl_bitfield<V1_4::RadioAccessFamily> networkTypeBitmap) override;
+    Return<void> setDataThrottlingResponse(const V1_6::RadioResponseInfo& info) override;
+    Return<void> getSystemSelectionChannelsResponse(
+            const V1_6::RadioResponseInfo& info,
+            const hidl_vec<V1_5::RadioAccessSpecifier>& specifiers) override;
+    Return<void> getCellInfoListResponse_1_6(const V1_6::RadioResponseInfo& info,
+                                             const hidl_vec<V1_6::CellInfo>& cellInfo) override;
+    Return<void> getSignalStrengthResponse_1_6(const V1_6::RadioResponseInfo& info,
+                                               const V1_6::SignalStrength& signalStrength) override;
+    Return<void> getVoiceRegistrationStateResponse_1_6(
+            const V1_6::RadioResponseInfo& info,
+            const V1_6::RegStateResult& voiceRegResponse) override;
+    Return<void> getDataRegistrationStateResponse_1_6(
+            const V1_6::RadioResponseInfo& info,
+            const V1_6::RegStateResult& dataRegResponse) override;
+    Return<void> getCurrentCallsResponse_1_6(const V1_6::RadioResponseInfo& info,
+                                             const hidl_vec<V1_6::Call>& calls) override;
+    Return<void> getSlicingConfigResponse(const V1_6::RadioResponseInfo& info,
+                                          const V1_6::SlicingConfig& slicingConfig) override;
+    Return<void> getSimPhonebookRecordsResponse(const V1_6::RadioResponseInfo& info) override;
+    Return<void> getSimPhonebookCapacityResponse(const V1_6::RadioResponseInfo& info,
+                                                 const V1_6::PhonebookCapacity& capacity) override;
+    Return<void> updateSimPhonebookRecordsResponse(const V1_6::RadioResponseInfo& info,
+                                                   int32_t updatedRecordIndex) override;
+
+  public:
+    RadioResponse(std::shared_ptr<DriverContext> context);
+
+    void setResponseFunction(
+            std::shared_ptr<::aidl::android::hardware::radio::data::IRadioDataResponse> dataCb);
+    void setResponseFunction(
+            std::shared_ptr<::aidl::android::hardware::radio::messaging::IRadioMessagingResponse>
+                    radioMessagingResponse);
+    void setResponseFunction(
+            std::shared_ptr<::aidl::android::hardware::radio::modem::IRadioModemResponse> modemCb);
+    void setResponseFunction(
+            std::shared_ptr<::aidl::android::hardware::radio::network::IRadioNetworkResponse> nwCb);
+    void setResponseFunction(
+            std::shared_ptr<::aidl::android::hardware::radio::sim::IRadioSimResponse> simCb);
+    void setResponseFunction(
+            std::shared_ptr<::aidl::android::hardware::radio::voice::IRadioVoiceResponse> voiceCb);
+
+    std::shared_ptr<::aidl::android::hardware::radio::data::IRadioDataResponse> dataCb();
+    std::shared_ptr<::aidl::android::hardware::radio::messaging::IRadioMessagingResponse>
+    messagingCb();
+    std::shared_ptr<::aidl::android::hardware::radio::modem::IRadioModemResponse> modemCb();
+    std::shared_ptr<::aidl::android::hardware::radio::network::IRadioNetworkResponse> networkCb();
+    std::shared_ptr<::aidl::android::hardware::radio::sim::IRadioSimResponse> simCb();
+    std::shared_ptr<::aidl::android::hardware::radio::voice::IRadioVoiceResponse> voiceCb();
+};
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioSim.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioSim.h
new file mode 100644
index 0000000..84bb68b
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioSim.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include "RadioCompatBase.h"
+
+#include <aidl/android/hardware/radio/sim/BnRadioSim.h>
+
+namespace android::hardware::radio::compat {
+
+class RadioSim : public RadioCompatBase, public aidl::android::hardware::radio::sim::BnRadioSim {
+    std::shared_ptr<::aidl::android::hardware::radio::sim::IRadioSimResponse> respond();
+
+    ::ndk::ScopedAStatus areUiccApplicationsEnabled(int32_t serial) override;
+    ::ndk::ScopedAStatus changeIccPin2ForApp(int32_t serial, const std::string& oldPin2,
+                                             const std::string& newPin2,
+                                             const std::string& aid) override;
+    ::ndk::ScopedAStatus changeIccPinForApp(int32_t serial, const std::string& oldPin,
+                                            const std::string& newPin,
+                                            const std::string& aid) override;
+    ::ndk::ScopedAStatus enableUiccApplications(int32_t serial, bool enable) override;
+    ::ndk::ScopedAStatus getAllowedCarriers(int32_t serial) override;
+    ::ndk::ScopedAStatus getCdmaSubscription(int32_t serial) override;
+    ::ndk::ScopedAStatus getCdmaSubscriptionSource(int32_t serial) override;
+    ::ndk::ScopedAStatus getFacilityLockForApp(int32_t serial, const std::string& facility,
+                                               const std::string& password, int32_t serviceClass,
+                                               const std::string& appId) override;
+    ::ndk::ScopedAStatus getIccCardStatus(int32_t serial) override;
+    ::ndk::ScopedAStatus getImsiForApp(int32_t serial, const std::string& aid) override;
+    ::ndk::ScopedAStatus getSimPhonebookCapacity(int32_t serial) override;
+    ::ndk::ScopedAStatus getSimPhonebookRecords(int32_t serial) override;
+    ::ndk::ScopedAStatus iccCloseLogicalChannel(int32_t serial, int32_t channelId) override;
+    ::ndk::ScopedAStatus iccIoForApp(
+            int32_t serial, const ::aidl::android::hardware::radio::sim::IccIo& iccIo) override;
+    ::ndk::ScopedAStatus iccOpenLogicalChannel(int32_t serial, const std::string& aid,
+                                               int32_t p2) override;
+    ::ndk::ScopedAStatus iccTransmitApduBasicChannel(
+            int32_t serial, const ::aidl::android::hardware::radio::sim::SimApdu& message) override;
+    ::ndk::ScopedAStatus iccTransmitApduLogicalChannel(
+            int32_t serial, const ::aidl::android::hardware::radio::sim::SimApdu& message) override;
+    ::ndk::ScopedAStatus reportStkServiceIsRunning(int32_t serial) override;
+    ::ndk::ScopedAStatus requestIccSimAuthentication(int32_t serial, int32_t authContext,
+                                                     const std::string& authData,
+                                                     const std::string& aid) override;
+    ::ndk::ScopedAStatus responseAcknowledgement() override;
+    ::ndk::ScopedAStatus sendEnvelope(int32_t serial, const std::string& command) override;
+    ::ndk::ScopedAStatus sendEnvelopeWithStatus(int32_t serial,
+                                                const std::string& contents) override;
+    ::ndk::ScopedAStatus sendTerminalResponseToSim(int32_t serial,
+                                                   const std::string& commandResponse) override;
+    ::ndk::ScopedAStatus setAllowedCarriers(
+            int32_t serial,
+            const ::aidl::android::hardware::radio::sim::CarrierRestrictions& carriers,
+            ::aidl::android::hardware::radio::sim::SimLockMultiSimPolicy multiSimPolicy) override;
+    ::ndk::ScopedAStatus setCarrierInfoForImsiEncryption(
+            int32_t serial,
+            const ::aidl::android::hardware::radio::sim::ImsiEncryptionInfo& imsiEncryptionInfo)
+            override;
+    ::ndk::ScopedAStatus setCdmaSubscriptionSource(
+            int32_t serial,
+            ::aidl::android::hardware::radio::sim::CdmaSubscriptionSource cdmaSub) override;
+    ::ndk::ScopedAStatus setFacilityLockForApp(  //
+            int32_t serial, const std::string& facility, bool lockState, const std::string& passwd,
+            int32_t serviceClass, const std::string& appId) override;
+    ::ndk::ScopedAStatus setResponseFunctions(
+            const std::shared_ptr<::aidl::android::hardware::radio::sim::IRadioSimResponse>&
+                    radioSimResponse,
+            const std::shared_ptr<::aidl::android::hardware::radio::sim::IRadioSimIndication>&
+                    radioSimIndication) override;
+    ::ndk::ScopedAStatus setSimCardPower(
+            int32_t serial, ::aidl::android::hardware::radio::sim::CardPowerState powerUp) override;
+    ::ndk::ScopedAStatus setUiccSubscription(
+            int32_t serial,
+            const ::aidl::android::hardware::radio::sim::SelectUiccSub& uiccSub) override;
+    ::ndk::ScopedAStatus supplyIccPin2ForApp(int32_t serial, const std::string& pin2,
+                                             const std::string& aid) override;
+    ::ndk::ScopedAStatus supplyIccPinForApp(int32_t serial, const std::string& pin,
+                                            const std::string& aid) override;
+    ::ndk::ScopedAStatus supplyIccPuk2ForApp(int32_t serial, const std::string& puk2,
+                                             const std::string& pin2,
+                                             const std::string& aid) override;
+    ::ndk::ScopedAStatus supplyIccPukForApp(int32_t serial, const std::string& puk,
+                                            const std::string& pin,
+                                            const std::string& aid) override;
+    ::ndk::ScopedAStatus supplySimDepersonalization(
+            int32_t serial, ::aidl::android::hardware::radio::sim::PersoSubstate persoType,
+            const std::string& controlKey) override;
+    ::ndk::ScopedAStatus updateSimPhonebookRecords(
+            int32_t serial,
+            const ::aidl::android::hardware::radio::sim::PhonebookRecordInfo& recordInfo) override;
+
+  public:
+    using RadioCompatBase::RadioCompatBase;
+};
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioVoice.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioVoice.h
new file mode 100644
index 0000000..0f1d5fd
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioVoice.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include "RadioCompatBase.h"
+
+#include <aidl/android/hardware/radio/voice/BnRadioVoice.h>
+
+namespace android::hardware::radio::compat {
+
+class RadioVoice : public RadioCompatBase,
+                   public aidl::android::hardware::radio::voice::BnRadioVoice {
+    std::shared_ptr<::aidl::android::hardware::radio::voice::IRadioVoiceResponse> respond();
+
+    ::ndk::ScopedAStatus acceptCall(int32_t serial) override;
+    ::ndk::ScopedAStatus cancelPendingUssd(int32_t serial) override;
+    ::ndk::ScopedAStatus conference(int32_t serial) override;
+    ::ndk::ScopedAStatus dial(
+            int32_t serial, const ::aidl::android::hardware::radio::voice::Dial& dialInfo) override;
+    ::ndk::ScopedAStatus emergencyDial(
+            int32_t serial, const ::aidl::android::hardware::radio::voice::Dial& dialInfo,
+            int32_t categories, const std::vector<std::string>& urns,
+            ::aidl::android::hardware::radio::voice::EmergencyCallRouting routing,
+            bool hasKnownUserIntentEmergency, bool isTesting) override;
+    ::ndk::ScopedAStatus exitEmergencyCallbackMode(int32_t serial) override;
+    ::ndk::ScopedAStatus explicitCallTransfer(int32_t serial) override;
+    ::ndk::ScopedAStatus getCallForwardStatus(
+            int32_t serial,
+            const ::aidl::android::hardware::radio::voice::CallForwardInfo& callInfo) override;
+    ::ndk::ScopedAStatus getCallWaiting(int32_t serial, int32_t serviceClass) override;
+    ::ndk::ScopedAStatus getClip(int32_t serial) override;
+    ::ndk::ScopedAStatus getClir(int32_t serial) override;
+    ::ndk::ScopedAStatus getCurrentCalls(int32_t serial) override;
+    ::ndk::ScopedAStatus getLastCallFailCause(int32_t serial) override;
+    ::ndk::ScopedAStatus getMute(int32_t serial) override;
+    ::ndk::ScopedAStatus getPreferredVoicePrivacy(int32_t serial) override;
+    ::ndk::ScopedAStatus getTtyMode(int32_t serial) override;
+    ::ndk::ScopedAStatus handleStkCallSetupRequestFromSim(int32_t serial, bool accept) override;
+    ::ndk::ScopedAStatus hangup(int32_t serial, int32_t gsmIndex) override;
+    ::ndk::ScopedAStatus hangupForegroundResumeBackground(int32_t serial) override;
+    ::ndk::ScopedAStatus hangupWaitingOrBackground(int32_t serial) override;
+    ::ndk::ScopedAStatus isVoNrEnabled(int32_t serial) override;
+    ::ndk::ScopedAStatus rejectCall(int32_t serial) override;
+    ::ndk::ScopedAStatus responseAcknowledgement() override;
+    ::ndk::ScopedAStatus sendBurstDtmf(int32_t serial, const std::string& dtmf, int32_t on,
+                                       int32_t off) override;
+    ::ndk::ScopedAStatus sendCdmaFeatureCode(int32_t serial, const std::string& fcode) override;
+    ::ndk::ScopedAStatus sendDtmf(int32_t serial, const std::string& s) override;
+    ::ndk::ScopedAStatus sendUssd(int32_t serial, const std::string& ussd) override;
+    ::ndk::ScopedAStatus separateConnection(int32_t serial, int32_t gsmIndex) override;
+    ::ndk::ScopedAStatus setCallForward(
+            int32_t serial,
+            const ::aidl::android::hardware::radio::voice::CallForwardInfo& callInfo) override;
+    ::ndk::ScopedAStatus setCallWaiting(int32_t serial, bool enable, int32_t serviceClass) override;
+    ::ndk::ScopedAStatus setClir(int32_t serial, int32_t status) override;
+    ::ndk::ScopedAStatus setMute(int32_t serial, bool enable) override;
+    ::ndk::ScopedAStatus setPreferredVoicePrivacy(int32_t serial, bool enable) override;
+    ::ndk::ScopedAStatus setResponseFunctions(
+            const std::shared_ptr<::aidl::android::hardware::radio::voice::IRadioVoiceResponse>&
+                    radioVoiceResponse,
+            const std::shared_ptr<::aidl::android::hardware::radio::voice::IRadioVoiceIndication>&
+                    radioVoiceIndication) override;
+    ::ndk::ScopedAStatus setTtyMode(int32_t serial,
+                                    ::aidl::android::hardware::radio::voice::TtyMode mode) override;
+    ::ndk::ScopedAStatus setVoNrEnabled(int32_t serial, bool enable) override;
+    ::ndk::ScopedAStatus startDtmf(int32_t serial, const std::string& s) override;
+    ::ndk::ScopedAStatus stopDtmf(int32_t serial) override;
+    ::ndk::ScopedAStatus switchWaitingOrHoldingAndActive(int32_t serial) override;
+
+  public:
+    using RadioCompatBase::RadioCompatBase;
+};
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/messaging/RadioIndication-messaging.cpp b/radio/aidl/compat/libradiocompat/messaging/RadioIndication-messaging.cpp
new file mode 100644
index 0000000..eb87828
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/messaging/RadioIndication-messaging.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libradiocompat/RadioIndication.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#define RADIO_MODULE "MessagingIndication"
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::messaging;
+
+void RadioIndication::setResponseFunction(std::shared_ptr<aidl::IRadioMessagingIndication> rmiCb) {
+    mMessagingCb = rmiCb;
+}
+
+std::shared_ptr<aidl::IRadioMessagingIndication> RadioIndication::messagingCb() {
+    return mMessagingCb.get();
+}
+
+Return<void> RadioIndication::cdmaNewSms(V1_0::RadioIndicationType type,
+                                         const V1_0::CdmaSmsMessage& msg) {
+    LOG_CALL << type;
+    messagingCb()->cdmaNewSms(toAidl(type), toAidl(msg));
+    return {};
+}
+
+Return<void> RadioIndication::cdmaRuimSmsStorageFull(V1_0::RadioIndicationType type) {
+    LOG_CALL << type;
+    messagingCb()->cdmaRuimSmsStorageFull(toAidl(type));
+    return {};
+}
+
+Return<void> RadioIndication::newBroadcastSms(V1_0::RadioIndicationType type,
+                                              const hidl_vec<uint8_t>& data) {
+    LOG_CALL << type;
+    messagingCb()->newBroadcastSms(toAidl(type), data);
+    return {};
+}
+
+Return<void> RadioIndication::newSms(V1_0::RadioIndicationType type, const hidl_vec<uint8_t>& pdu) {
+    LOG_CALL << type;
+    messagingCb()->newSms(toAidl(type), pdu);
+    return {};
+}
+
+Return<void> RadioIndication::newSmsOnSim(V1_0::RadioIndicationType type, int32_t recordNumber) {
+    LOG_CALL << type;
+    messagingCb()->newSmsOnSim(toAidl(type), recordNumber);
+    return {};
+}
+
+Return<void> RadioIndication::newSmsStatusReport(V1_0::RadioIndicationType type,
+                                                 const hidl_vec<uint8_t>& pdu) {
+    LOG_CALL << type;
+    messagingCb()->newSmsStatusReport(toAidl(type), pdu);
+    return {};
+}
+
+Return<void> RadioIndication::simSmsStorageFull(V1_0::RadioIndicationType type) {
+    LOG_CALL << type;
+    messagingCb()->simSmsStorageFull(toAidl(type));
+    return {};
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/messaging/RadioMessaging.cpp b/radio/aidl/compat/libradiocompat/messaging/RadioMessaging.cpp
new file mode 100644
index 0000000..56d49f1
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/messaging/RadioMessaging.cpp
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libradiocompat/RadioMessaging.h>
+
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "Messaging"
+
+namespace android::hardware::radio::compat {
+
+using ::ndk::ScopedAStatus;
+namespace aidl = ::aidl::android::hardware::radio::messaging;
+constexpr auto ok = &ScopedAStatus::ok;
+
+std::shared_ptr<aidl::IRadioMessagingResponse> RadioMessaging::respond() {
+    return mCallbackManager->response().messagingCb();
+}
+
+ScopedAStatus RadioMessaging::acknowledgeIncomingGsmSmsWithPdu(  //
+        int32_t serial, bool success, const std::string& ackPdu) {
+    LOG_CALL << serial << ' ' << success << ' ' << ackPdu;
+    mHal1_5->acknowledgeIncomingGsmSmsWithPdu(serial, success, ackPdu);
+    return ok();
+}
+
+ScopedAStatus RadioMessaging::acknowledgeLastIncomingCdmaSms(  //
+        int32_t serial, const aidl::CdmaSmsAck& smsAck) {
+    LOG_CALL << serial;
+    mHal1_5->acknowledgeLastIncomingCdmaSms(serial, toHidl(smsAck));
+    return ok();
+}
+
+ScopedAStatus RadioMessaging::acknowledgeLastIncomingGsmSms(  //
+        int32_t serial, bool success, aidl::SmsAcknowledgeFailCause cause) {
+    LOG_CALL << serial << ' ' << success;
+    mHal1_5->acknowledgeLastIncomingGsmSms(serial, success, V1_0::SmsAcknowledgeFailCause(cause));
+    return ok();
+}
+
+ScopedAStatus RadioMessaging::deleteSmsOnRuim(int32_t serial, int32_t index) {
+    LOG_CALL << serial << ' ' << index;
+    mHal1_5->deleteSmsOnRuim(serial, index);
+    return ok();
+}
+
+ScopedAStatus RadioMessaging::deleteSmsOnSim(int32_t serial, int32_t index) {
+    LOG_CALL << serial << ' ' << index;
+    mHal1_5->deleteSmsOnSim(serial, index);
+    return ok();
+}
+
+ScopedAStatus RadioMessaging::getCdmaBroadcastConfig(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getCdmaBroadcastConfig(serial);
+    return ok();
+}
+
+ScopedAStatus RadioMessaging::getGsmBroadcastConfig(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getGsmBroadcastConfig(serial);
+    return ok();
+}
+
+ScopedAStatus RadioMessaging::getSmscAddress(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getSmscAddress(serial);
+    return ok();
+}
+
+ScopedAStatus RadioMessaging::reportSmsMemoryStatus(int32_t serial, bool available) {
+    LOG_CALL << serial << ' ' << available;
+    mHal1_5->reportSmsMemoryStatus(serial, available);
+    return ok();
+}
+
+ScopedAStatus RadioMessaging::responseAcknowledgement() {
+    LOG_CALL;
+    mHal1_5->responseAcknowledgement();
+    return ok();
+}
+
+ScopedAStatus RadioMessaging::sendCdmaSms(int32_t serial, const aidl::CdmaSmsMessage& sms) {
+    LOG_CALL << serial;
+    if (mHal1_6) {
+        mHal1_6->sendCdmaSms_1_6(serial, toHidl(sms));
+    } else {
+        mHal1_5->sendCdmaSms(serial, toHidl(sms));
+    }
+    return ok();
+}
+
+ScopedAStatus RadioMessaging::sendCdmaSmsExpectMore(int32_t serial, const aidl::CdmaSmsMessage& m) {
+    LOG_CALL << serial;
+    if (mHal1_6) {
+        mHal1_6->sendCdmaSmsExpectMore_1_6(serial, toHidl(m));
+    } else {
+        mHal1_5->sendCdmaSmsExpectMore(serial, toHidl(m));
+    }
+    return ok();
+}
+
+ScopedAStatus RadioMessaging::sendImsSms(int32_t serial, const aidl::ImsSmsMessage& message) {
+    LOG_CALL << serial;
+    mHal1_5->sendImsSms(serial, toHidl(message));
+    return ok();
+}
+
+ScopedAStatus RadioMessaging::sendSms(int32_t serial, const aidl::GsmSmsMessage& message) {
+    LOG_CALL << serial;
+    if (mHal1_6) {
+        mHal1_6->sendSms_1_6(serial, toHidl(message));
+    } else {
+        mHal1_5->sendSms(serial, toHidl(message));
+    }
+    return ok();
+}
+
+ScopedAStatus RadioMessaging::sendSmsExpectMore(int32_t serial, const aidl::GsmSmsMessage& msg) {
+    LOG_CALL << serial;
+    if (mHal1_6) {
+        mHal1_6->sendSmsExpectMore_1_6(serial, toHidl(msg));
+    } else {
+        mHal1_5->sendSMSExpectMore(serial, toHidl(msg));
+    }
+    return ok();
+}
+
+ScopedAStatus RadioMessaging::setCdmaBroadcastActivation(int32_t serial, bool activate) {
+    LOG_CALL << serial << ' ' << activate;
+    mHal1_5->setCdmaBroadcastActivation(serial, activate);
+    return ok();
+}
+
+ScopedAStatus RadioMessaging::setCdmaBroadcastConfig(
+        int32_t serial, const std::vector<aidl::CdmaBroadcastSmsConfigInfo>& cfgInfo) {
+    LOG_CALL << serial;
+    mHal1_5->setCdmaBroadcastConfig(serial, toHidl(cfgInfo));
+    return ok();
+}
+
+ScopedAStatus RadioMessaging::setGsmBroadcastActivation(int32_t serial, bool activate) {
+    LOG_CALL << serial << ' ' << activate;
+    mHal1_5->setGsmBroadcastActivation(serial, activate);
+    return ok();
+}
+
+ScopedAStatus RadioMessaging::setGsmBroadcastConfig(
+        int32_t serial, const std::vector<aidl::GsmBroadcastSmsConfigInfo>& configInfo) {
+    LOG_CALL << serial;
+    mHal1_5->setGsmBroadcastConfig(serial, toHidl(configInfo));
+    return ok();
+}
+
+ScopedAStatus RadioMessaging::setResponseFunctions(
+        const std::shared_ptr<aidl::IRadioMessagingResponse>& response,
+        const std::shared_ptr<aidl::IRadioMessagingIndication>& indication) {
+    LOG_CALL << response << ' ' << indication;
+    mCallbackManager->setResponseFunctions(response, indication);
+    return ok();
+}
+
+ScopedAStatus RadioMessaging::setSmscAddress(int32_t serial, const std::string& smsc) {
+    LOG_CALL << serial << ' ' << smsc;
+    mHal1_5->setSmscAddress(serial, smsc);
+    return ok();
+}
+
+ScopedAStatus RadioMessaging::writeSmsToRuim(int32_t serial, const aidl::CdmaSmsWriteArgs& sms) {
+    LOG_CALL << serial;
+    mHal1_5->writeSmsToRuim(serial, toHidl(sms));
+    return ok();
+}
+
+ScopedAStatus RadioMessaging::writeSmsToSim(int32_t serial, const aidl::SmsWriteArgs& smsWrArgs) {
+    LOG_CALL << serial;
+    mHal1_5->writeSmsToSim(serial, toHidl(smsWrArgs));
+    return ok();
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/messaging/RadioResponse-messaging.cpp b/radio/aidl/compat/libradiocompat/messaging/RadioResponse-messaging.cpp
new file mode 100644
index 0000000..7a9273f
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/messaging/RadioResponse-messaging.cpp
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libradiocompat/RadioResponse.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "MessagingResponse"
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::messaging;
+
+void RadioResponse::setResponseFunction(std::shared_ptr<aidl::IRadioMessagingResponse> rmrCb) {
+    mMessagingCb = rmrCb;
+}
+
+std::shared_ptr<aidl::IRadioMessagingResponse> RadioResponse::messagingCb() {
+    return mMessagingCb.get();
+}
+
+Return<void> RadioResponse::acknowledgeIncomingGsmSmsWithPduResponse(
+        const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    messagingCb()->acknowledgeIncomingGsmSmsWithPduResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::acknowledgeLastIncomingCdmaSmsResponse(
+        const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    messagingCb()->acknowledgeLastIncomingCdmaSmsResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::acknowledgeLastIncomingGsmSmsResponse(
+        const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    messagingCb()->acknowledgeLastIncomingGsmSmsResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::deleteSmsOnRuimResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    messagingCb()->deleteSmsOnRuimResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::deleteSmsOnSimResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    messagingCb()->deleteSmsOnSimResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::getCdmaBroadcastConfigResponse(
+        const V1_0::RadioResponseInfo& info,
+        const hidl_vec<V1_0::CdmaBroadcastSmsConfigInfo>& configs) {
+    LOG_CALL << info.serial;
+    messagingCb()->getCdmaBroadcastConfigResponse(toAidl(info), toAidl(configs));
+    return {};
+}
+
+Return<void> RadioResponse::getGsmBroadcastConfigResponse(
+        const V1_0::RadioResponseInfo& info, const hidl_vec<V1_0::GsmBroadcastSmsConfigInfo>& cfg) {
+    LOG_CALL << info.serial;
+    messagingCb()->getGsmBroadcastConfigResponse(toAidl(info), toAidl(cfg));
+    return {};
+}
+
+Return<void> RadioResponse::getSmscAddressResponse(const V1_0::RadioResponseInfo& info,
+                                                   const hidl_string& smsc) {
+    LOG_CALL << info.serial;
+    messagingCb()->getSmscAddressResponse(toAidl(info), smsc);
+    return {};
+}
+
+Return<void> RadioResponse::reportSmsMemoryStatusResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    messagingCb()->reportSmsMemoryStatusResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::sendCdmaSmsExpectMoreResponse(const V1_0::RadioResponseInfo& info,
+                                                          const V1_0::SendSmsResult& sms) {
+    LOG_CALL << info.serial;
+    messagingCb()->sendCdmaSmsExpectMoreResponse(toAidl(info), toAidl(sms));
+    return {};
+}
+
+Return<void> RadioResponse::sendCdmaSmsExpectMoreResponse_1_6(const V1_6::RadioResponseInfo& info,
+                                                              const V1_0::SendSmsResult& sms) {
+    LOG_CALL << info.serial;
+    messagingCb()->sendCdmaSmsExpectMoreResponse(toAidl(info), toAidl(sms));
+    return {};
+}
+
+Return<void> RadioResponse::sendCdmaSmsResponse(const V1_0::RadioResponseInfo& info,
+                                                const V1_0::SendSmsResult& sms) {
+    LOG_CALL << info.serial;
+    messagingCb()->sendCdmaSmsResponse(toAidl(info), toAidl(sms));
+    return {};
+}
+
+Return<void> RadioResponse::sendCdmaSmsResponse_1_6(const V1_6::RadioResponseInfo& info,
+                                                    const V1_0::SendSmsResult& sms) {
+    LOG_CALL << info.serial;
+    messagingCb()->sendCdmaSmsResponse(toAidl(info), toAidl(sms));
+    return {};
+}
+
+Return<void> RadioResponse::sendImsSmsResponse(const V1_0::RadioResponseInfo& info,
+                                               const V1_0::SendSmsResult& sms) {
+    LOG_CALL << info.serial;
+    messagingCb()->sendImsSmsResponse(toAidl(info), toAidl(sms));
+    return {};
+}
+
+Return<void> RadioResponse::sendSMSExpectMoreResponse(const V1_0::RadioResponseInfo& info,
+                                                      const V1_0::SendSmsResult& sms) {
+    LOG_CALL << info.serial;
+    messagingCb()->sendSmsExpectMoreResponse(toAidl(info), toAidl(sms));
+    return {};
+}
+
+Return<void> RadioResponse::sendSmsExpectMoreResponse_1_6(const V1_6::RadioResponseInfo& info,
+                                                          const V1_0::SendSmsResult& sms) {
+    LOG_CALL << info.serial;
+    messagingCb()->sendSmsExpectMoreResponse(toAidl(info), toAidl(sms));
+    return {};
+}
+
+Return<void> RadioResponse::sendSmsResponse(const V1_0::RadioResponseInfo& info,
+                                            const V1_0::SendSmsResult& sms) {
+    LOG_CALL << info.serial;
+    messagingCb()->sendSmsResponse(toAidl(info), toAidl(sms));
+    return {};
+}
+
+Return<void> RadioResponse::sendSmsResponse_1_6(const V1_6::RadioResponseInfo& info,
+                                                const V1_0::SendSmsResult& sms) {
+    LOG_CALL << info.serial;
+    messagingCb()->sendSmsResponse(toAidl(info), toAidl(sms));
+    return {};
+}
+
+Return<void> RadioResponse::setCdmaBroadcastActivationResponse(
+        const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    messagingCb()->setCdmaBroadcastActivationResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setCdmaBroadcastConfigResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    messagingCb()->setCdmaBroadcastConfigResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setGsmBroadcastActivationResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    messagingCb()->setGsmBroadcastActivationResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setGsmBroadcastConfigResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    messagingCb()->setGsmBroadcastConfigResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setSmscAddressResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    messagingCb()->setSmscAddressResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::writeSmsToRuimResponse(const V1_0::RadioResponseInfo& info,
+                                                   uint32_t index) {
+    LOG_CALL << info.serial << ' ' << index;
+    messagingCb()->writeSmsToRuimResponse(toAidl(info), index);
+    return {};
+}
+
+Return<void> RadioResponse::writeSmsToSimResponse(const V1_0::RadioResponseInfo& info,
+                                                  int32_t index) {
+    LOG_CALL << info.serial << ' ' << index;
+    messagingCb()->writeSmsToSimResponse(toAidl(info), index);
+    return {};
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/messaging/structs.cpp b/radio/aidl/compat/libradiocompat/messaging/structs.cpp
new file mode 100644
index 0000000..9019680
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/messaging/structs.cpp
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "structs.h"
+
+#include "collections.h"
+
+#include <aidl/android/hardware/radio/messaging/CdmaSmsAddress.h>
+#include <android-base/logging.h>
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::messaging;
+
+V1_0::CdmaSmsAck toHidl(const aidl::CdmaSmsAck& smsAck) {
+    return {
+            .errorClass = (smsAck.errorClass ? V1_0::CdmaSmsErrorClass::ERROR
+                                             : V1_0::CdmaSmsErrorClass::NO_ERROR),
+            .smsCauseCode = smsAck.smsCauseCode,
+    };
+}
+
+static aidl::CdmaSmsAddress toAidl(const V1_0::CdmaSmsAddress& addr) {
+    return {
+            .digitMode = static_cast<int32_t>(addr.digitMode),
+            .isNumberModeDataNetwork = addr.numberMode == V1_0::CdmaSmsNumberMode::DATA_NETWORK,
+            .numberType = static_cast<int32_t>(addr.numberType),
+            .numberPlan = static_cast<int32_t>(addr.numberPlan),
+            .digits = addr.digits,
+    };
+}
+
+static V1_0::CdmaSmsAddress toHidl(const aidl::CdmaSmsAddress& addr) {
+    return {
+            .digitMode = 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},
+            .digits = addr.digits,
+    };
+}
+
+static aidl::CdmaSmsSubaddress toAidl(const V1_0::CdmaSmsSubaddress& addr) {
+    return {
+            .subaddressType = static_cast<int32_t>(addr.subaddressType),
+            .odd = addr.odd,
+            .digits = addr.digits,
+    };
+}
+
+static V1_0::CdmaSmsSubaddress toHidl(const aidl::CdmaSmsSubaddress& addr) {
+    return {
+            .subaddressType = V1_0::CdmaSmsSubaddressType{addr.subaddressType},
+            .odd = addr.odd,
+            .digits = addr.digits,
+    };
+}
+
+::aidl::android::hardware::radio::messaging::CdmaSmsMessage toAidl(const V1_0::CdmaSmsMessage& m) {
+    return {
+            .teleserviceId = m.teleserviceId,
+            .isServicePresent = m.isServicePresent,
+            .serviceCategory = m.serviceCategory,
+            .address = toAidl(m.address),
+            .subAddress = toAidl(m.subAddress),
+            .bearerData = m.bearerData,
+    };
+}
+
+V1_0::CdmaSmsMessage toHidl(const aidl::CdmaSmsMessage& msg) {
+    return {
+            .teleserviceId = msg.teleserviceId,
+            .isServicePresent = msg.isServicePresent,
+            .serviceCategory = msg.serviceCategory,
+            .address = toHidl(msg.address),
+            .subAddress = toHidl(msg.subAddress),
+            .bearerData = msg.bearerData,
+    };
+}
+
+V1_0::ImsSmsMessage toHidl(const aidl::ImsSmsMessage& msg) {
+    return {
+            .tech = V1_0::RadioTechnologyFamily{msg.tech},
+            .retry = msg.retry,
+            .messageRef = msg.messageRef,
+            .cdmaMessage = toHidl(msg.cdmaMessage),
+            .gsmMessage = toHidl(msg.gsmMessage),
+    };
+}
+
+V1_0::GsmSmsMessage toHidl(const aidl::GsmSmsMessage& msg) {
+    return {
+            .smscPdu = msg.smscPdu,
+            .pdu = msg.pdu,
+    };
+}
+
+aidl::CdmaBroadcastSmsConfigInfo toAidl(const V1_0::CdmaBroadcastSmsConfigInfo& info) {
+    return {
+            .serviceCategory = info.serviceCategory,
+            .language = info.language,
+            .selected = info.selected,
+    };
+}
+
+V1_0::CdmaBroadcastSmsConfigInfo toHidl(const aidl::CdmaBroadcastSmsConfigInfo& info) {
+    return {
+            .serviceCategory = info.serviceCategory,
+            .language = info.language,
+            .selected = info.selected,
+    };
+}
+
+aidl::GsmBroadcastSmsConfigInfo toAidl(const V1_0::GsmBroadcastSmsConfigInfo& info) {
+    return {
+            .fromServiceId = info.fromServiceId,
+            .toServiceId = info.toServiceId,
+            .fromCodeScheme = info.fromCodeScheme,
+            .toCodeScheme = info.toCodeScheme,
+            .selected = info.selected,
+    };
+}
+
+V1_0::GsmBroadcastSmsConfigInfo toHidl(const aidl::GsmBroadcastSmsConfigInfo& info) {
+    return {
+            .fromServiceId = info.fromServiceId,
+            .toServiceId = info.toServiceId,
+            .fromCodeScheme = info.fromCodeScheme,
+            .toCodeScheme = info.toCodeScheme,
+            .selected = info.selected,
+    };
+}
+
+V1_0::CdmaSmsWriteArgs toHidl(const aidl::CdmaSmsWriteArgs& args) {
+    return {
+            .status = V1_0::CdmaSmsWriteArgsStatus{args.status},
+            .message = toHidl(args.message),
+    };
+}
+
+V1_0::SmsWriteArgs toHidl(const aidl::SmsWriteArgs& args) {
+    return {
+            .status = V1_0::SmsWriteArgsStatus{args.status},
+            .pdu = args.pdu,
+            .smsc = args.smsc,
+    };
+}
+
+::aidl::android::hardware::radio::messaging::SendSmsResult toAidl(
+        const V1_0::SendSmsResult& result) {
+    return {
+            .messageRef = result.messageRef,
+            .ackPDU = result.ackPDU,
+            .errorCode = result.errorCode,
+    };
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/messaging/structs.h b/radio/aidl/compat/libradiocompat/messaging/structs.h
new file mode 100644
index 0000000..afb4941
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/messaging/structs.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <aidl/android/hardware/radio/messaging/CdmaBroadcastSmsConfigInfo.h>
+#include <aidl/android/hardware/radio/messaging/CdmaSmsAck.h>
+#include <aidl/android/hardware/radio/messaging/CdmaSmsMessage.h>
+#include <aidl/android/hardware/radio/messaging/CdmaSmsWriteArgs.h>
+#include <aidl/android/hardware/radio/messaging/GsmBroadcastSmsConfigInfo.h>
+#include <aidl/android/hardware/radio/messaging/GsmSmsMessage.h>
+#include <aidl/android/hardware/radio/messaging/ImsSmsMessage.h>
+#include <aidl/android/hardware/radio/messaging/SendSmsResult.h>
+#include <aidl/android/hardware/radio/messaging/SmsWriteArgs.h>
+#include <android/hardware/radio/1.0/types.h>
+
+namespace android::hardware::radio::compat {
+
+V1_0::CdmaSmsAck toHidl(const ::aidl::android::hardware::radio::messaging::CdmaSmsAck& ack);
+
+::aidl::android::hardware::radio::messaging::CdmaSmsMessage toAidl(const V1_0::CdmaSmsMessage& msg);
+V1_0::CdmaSmsMessage toHidl(const ::aidl::android::hardware::radio::messaging::CdmaSmsMessage& msg);
+
+V1_0::ImsSmsMessage toHidl(const ::aidl::android::hardware::radio::messaging::ImsSmsMessage& msg);
+
+V1_0::GsmSmsMessage toHidl(const ::aidl::android::hardware::radio::messaging::GsmSmsMessage& msg);
+
+::aidl::android::hardware::radio::messaging::CdmaBroadcastSmsConfigInfo  //
+toAidl(const V1_0::CdmaBroadcastSmsConfigInfo& info);
+V1_0::CdmaBroadcastSmsConfigInfo  //
+toHidl(const ::aidl::android::hardware::radio::messaging::CdmaBroadcastSmsConfigInfo& info);
+
+::aidl::android::hardware::radio::messaging::GsmBroadcastSmsConfigInfo  //
+toAidl(const V1_0::GsmBroadcastSmsConfigInfo& info);
+V1_0::GsmBroadcastSmsConfigInfo  //
+toHidl(const ::aidl::android::hardware::radio::messaging::GsmBroadcastSmsConfigInfo& info);
+
+V1_0::CdmaSmsWriteArgs  //
+toHidl(const ::aidl::android::hardware::radio::messaging::CdmaSmsWriteArgs& args);
+
+V1_0::SmsWriteArgs toHidl(const ::aidl::android::hardware::radio::messaging::SmsWriteArgs& args);
+
+::aidl::android::hardware::radio::messaging::SendSmsResult toAidl(const V1_0::SendSmsResult& res);
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/modem/RadioIndication-modem.cpp b/radio/aidl/compat/libradiocompat/modem/RadioIndication-modem.cpp
new file mode 100644
index 0000000..851c93b
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/modem/RadioIndication-modem.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libradiocompat/RadioIndication.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "ModemIndication"
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::modem;
+
+void RadioIndication::setResponseFunction(std::shared_ptr<aidl::IRadioModemIndication> modemCb) {
+    mModemCb = modemCb;
+}
+
+std::shared_ptr<aidl::IRadioModemIndication> RadioIndication::modemCb() {
+    return mModemCb.get();
+}
+
+Return<void> RadioIndication::hardwareConfigChanged(V1_0::RadioIndicationType type,
+                                                    const hidl_vec<V1_0::HardwareConfig>& configs) {
+    LOG_CALL << type;
+    modemCb()->hardwareConfigChanged(toAidl(type), toAidl(configs));
+    return {};
+}
+
+Return<void> RadioIndication::modemReset(V1_0::RadioIndicationType type, const hidl_string& reasn) {
+    LOG_CALL << type;
+    modemCb()->modemReset(toAidl(type), reasn);
+    return {};
+}
+
+Return<void> RadioIndication::radioCapabilityIndication(V1_0::RadioIndicationType type,
+                                                        const V1_0::RadioCapability& rc) {
+    LOG_CALL << type;
+    modemCb()->radioCapabilityIndication(toAidl(type), toAidl(rc));
+    return {};
+}
+
+Return<void> RadioIndication::radioStateChanged(V1_0::RadioIndicationType t, V1_0::RadioState st) {
+    LOG_CALL << t;
+    modemCb()->radioStateChanged(toAidl(t), aidl::RadioState(st));
+    return {};
+}
+
+Return<void> RadioIndication::rilConnected(V1_0::RadioIndicationType type) {
+    LOG_CALL << type;
+    modemCb()->rilConnected(toAidl(type));
+    return {};
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/modem/RadioModem.cpp b/radio/aidl/compat/libradiocompat/modem/RadioModem.cpp
new file mode 100644
index 0000000..d28b940
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/modem/RadioModem.cpp
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libradiocompat/RadioModem.h>
+
+#include "debug.h"
+#include "structs.h"
+
+#define RADIO_MODULE "Modem"
+
+namespace android::hardware::radio::compat {
+
+using ::ndk::ScopedAStatus;
+namespace aidl = ::aidl::android::hardware::radio::modem;
+constexpr auto ok = &ScopedAStatus::ok;
+
+std::shared_ptr<aidl::IRadioModemResponse> RadioModem::respond() {
+    return mCallbackManager->response().modemCb();
+}
+
+ScopedAStatus RadioModem::enableModem(int32_t serial, bool on) {
+    LOG_CALL << serial;
+    mHal1_5->enableModem(serial, on);
+    return ok();
+}
+
+ScopedAStatus RadioModem::getBasebandVersion(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getBasebandVersion(serial);
+    return ok();
+}
+
+ScopedAStatus RadioModem::getDeviceIdentity(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getDeviceIdentity(serial);
+    return ok();
+}
+
+ScopedAStatus RadioModem::getHardwareConfig(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getHardwareConfig(serial);
+    return ok();
+}
+
+ScopedAStatus RadioModem::getModemActivityInfo(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getModemActivityInfo(serial);
+    return ok();
+}
+
+ScopedAStatus RadioModem::getModemStackStatus(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getModemStackStatus(serial);
+    return ok();
+}
+
+ScopedAStatus RadioModem::getRadioCapability(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getRadioCapability(serial);
+    return ok();
+}
+
+ScopedAStatus RadioModem::nvReadItem(int32_t serial, aidl::NvItem itemId) {
+    LOG_CALL << serial;
+    mHal1_5->nvReadItem(serial, V1_0::NvItem(itemId));
+    return ok();
+}
+
+ScopedAStatus RadioModem::nvResetConfig(int32_t serial, aidl::ResetNvType resetType) {
+    LOG_CALL << serial;
+    mHal1_5->nvResetConfig(serial, V1_0::ResetNvType(resetType));
+    return ok();
+}
+
+ScopedAStatus RadioModem::nvWriteCdmaPrl(int32_t serial, const std::vector<uint8_t>& prl) {
+    LOG_CALL << serial;
+    mHal1_5->nvWriteCdmaPrl(serial, prl);
+    return ok();
+}
+
+ScopedAStatus RadioModem::nvWriteItem(int32_t serial, const aidl::NvWriteItem& item) {
+    LOG_CALL << serial;
+    mHal1_5->nvWriteItem(serial, toHidl(item));
+    return ok();
+}
+
+ScopedAStatus RadioModem::requestShutdown(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->requestShutdown(serial);
+    return ok();
+}
+
+ScopedAStatus RadioModem::responseAcknowledgement() {
+    LOG_CALL;
+    mHal1_5->responseAcknowledgement();
+    return ok();
+}
+
+ScopedAStatus RadioModem::sendDeviceState(int32_t serial, aidl::DeviceStateType type, bool state) {
+    LOG_CALL << serial;
+    mHal1_5->sendDeviceState(serial, V1_0::DeviceStateType(type), state);
+    return ok();
+}
+
+ScopedAStatus RadioModem::setRadioCapability(int32_t serial, const aidl::RadioCapability& rc) {
+    LOG_CALL << serial;
+    mHal1_5->setRadioCapability(serial, toHidl(rc));
+    return ok();
+}
+
+ScopedAStatus RadioModem::setRadioPower(int32_t serial, bool powerOn, bool forEmergencyCall,
+                                        bool preferredForEmergencyCall) {
+    LOG_CALL << serial;
+    if (mHal1_6) {
+        mHal1_6->setRadioPower_1_6(serial, powerOn, forEmergencyCall, preferredForEmergencyCall);
+    } else {
+        mHal1_5->setRadioPower_1_5(serial, powerOn, forEmergencyCall, preferredForEmergencyCall);
+    }
+    return ok();
+}
+
+ScopedAStatus RadioModem::setResponseFunctions(
+        const std::shared_ptr<aidl::IRadioModemResponse>& response,
+        const std::shared_ptr<aidl::IRadioModemIndication>& indication) {
+    LOG_CALL << response << ' ' << indication;
+    mCallbackManager->setResponseFunctions(response, indication);
+    return ok();
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/modem/RadioResponse-modem.cpp b/radio/aidl/compat/libradiocompat/modem/RadioResponse-modem.cpp
new file mode 100644
index 0000000..6e1a962
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/modem/RadioResponse-modem.cpp
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libradiocompat/RadioResponse.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "ModemResponse"
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::modem;
+
+void RadioResponse::setResponseFunction(std::shared_ptr<aidl::IRadioModemResponse> modemCb) {
+    mModemCb = modemCb;
+}
+
+std::shared_ptr<aidl::IRadioModemResponse> RadioResponse::modemCb() {
+    return mModemCb.get();
+}
+
+Return<void> RadioResponse::enableModemResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    modemCb()->enableModemResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::getBasebandVersionResponse(const V1_0::RadioResponseInfo& info,
+                                                       const hidl_string& version) {
+    LOG_CALL << info.serial;
+    modemCb()->getBasebandVersionResponse(toAidl(info), version);
+    return {};
+}
+
+Return<void> RadioResponse::getDeviceIdentityResponse(  //
+        const V1_0::RadioResponseInfo& info, const hidl_string& imei, const hidl_string& imeisv,
+        const hidl_string& esn, const hidl_string& meid) {
+    LOG_CALL << info.serial;
+    modemCb()->getDeviceIdentityResponse(toAidl(info), imei, imeisv, esn, meid);
+    return {};
+}
+
+Return<void> RadioResponse::getHardwareConfigResponse(
+        const V1_0::RadioResponseInfo& info, const hidl_vec<V1_0::HardwareConfig>& config) {
+    LOG_CALL << info.serial;
+    modemCb()->getHardwareConfigResponse(toAidl(info), toAidl(config));
+    return {};
+}
+
+Return<void> RadioResponse::getModemActivityInfoResponse(
+        const V1_0::RadioResponseInfo& info, const V1_0::ActivityStatsInfo& activityInfo) {
+    LOG_CALL << info.serial;
+    modemCb()->getModemActivityInfoResponse(toAidl(info), toAidl(activityInfo));
+    return {};
+}
+
+Return<void> RadioResponse::getModemStackStatusResponse(const V1_0::RadioResponseInfo& info,
+                                                        bool isEnabled) {
+    LOG_CALL << info.serial;
+    modemCb()->getModemStackStatusResponse(toAidl(info), isEnabled);
+    return {};
+}
+
+Return<void> RadioResponse::getRadioCapabilityResponse(const V1_0::RadioResponseInfo& info,
+                                                       const V1_0::RadioCapability& rc) {
+    LOG_CALL << info.serial;
+    modemCb()->getRadioCapabilityResponse(toAidl(info), toAidl(rc));
+    return {};
+}
+
+Return<void> RadioResponse::nvReadItemResponse(const V1_0::RadioResponseInfo& info,
+                                               const hidl_string& result) {
+    LOG_CALL << info.serial;
+    modemCb()->nvReadItemResponse(toAidl(info), result);
+    return {};
+}
+
+Return<void> RadioResponse::nvResetConfigResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    modemCb()->nvResetConfigResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::nvWriteCdmaPrlResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    modemCb()->nvWriteCdmaPrlResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::nvWriteItemResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    modemCb()->nvWriteItemResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::requestShutdownResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    modemCb()->requestShutdownResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::sendDeviceStateResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    modemCb()->sendDeviceStateResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setRadioCapabilityResponse(const V1_0::RadioResponseInfo& info,
+                                                       const V1_0::RadioCapability& rc) {
+    LOG_CALL << info.serial;
+    modemCb()->setRadioCapabilityResponse(toAidl(info), toAidl(rc));
+    return {};
+}
+
+Return<void> RadioResponse::setRadioPowerResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    modemCb()->setRadioPowerResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setRadioPowerResponse_1_5(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    modemCb()->setRadioPowerResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setRadioPowerResponse_1_6(const V1_6::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    modemCb()->setRadioPowerResponse(toAidl(info));
+    return {};
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/modem/structs.cpp b/radio/aidl/compat/libradiocompat/modem/structs.cpp
new file mode 100644
index 0000000..69e651b
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/modem/structs.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "structs.h"
+
+#include "commonStructs.h"
+
+#include "collections.h"
+
+#include <android-base/logging.h>
+
+namespace android::hardware::radio::compat {
+
+using ::aidl::android::hardware::radio::AccessNetwork;
+using ::aidl::android::hardware::radio::RadioTechnology;
+namespace aidl = ::aidl::android::hardware::radio::modem;
+
+V1_0::NvWriteItem toHidl(const aidl::NvWriteItem& item) {
+    return {
+            .itemId = V1_0::NvItem{item.itemId},
+            .value = item.value,
+    };
+}
+
+aidl::RadioCapability toAidl(const V1_0::RadioCapability& capa) {
+    return {
+            .session = capa.session,
+            .phase = static_cast<int32_t>(capa.phase),
+            .raf = static_cast<int32_t>(capa.raf),
+            .logicalModemUuid = capa.logicalModemUuid,
+            .status = static_cast<int32_t>(capa.status),
+    };
+}
+
+V1_0::RadioCapability toHidl(const aidl::RadioCapability& capa) {
+    return {
+            .session = capa.session,
+            .phase = V1_0::RadioCapabilityPhase{capa.phase},
+            .raf = toHidlBitfield<V1_0::RadioAccessFamily>(capa.raf),
+            .logicalModemUuid = capa.logicalModemUuid,
+            .status = V1_0::RadioCapabilityStatus{capa.status},
+    };
+}
+
+aidl::HardwareConfig toAidl(const V1_0::HardwareConfig& config) {
+    return {
+            .type = static_cast<int32_t>(config.type),
+            .uuid = config.uuid,
+            .state = static_cast<int32_t>(config.state),
+            .modem = toAidl(config.modem),
+            .sim = toAidl(config.sim),
+    };
+}
+
+aidl::HardwareConfigModem toAidl(const V1_0::HardwareConfigModem& modem) {
+    return {
+            .rilModel = modem.rilModel,
+            .rat = RadioTechnology(modem.rat),
+            .maxVoiceCalls = modem.maxVoice,
+            .maxDataCalls = modem.maxData,
+            .maxStandby = modem.maxStandby,
+    };
+}
+
+aidl::HardwareConfigSim toAidl(const V1_0::HardwareConfigSim& sim) {
+    return {
+            .modemUuid = sim.modemUuid,
+    };
+}
+
+aidl::ActivityStatsInfo toAidl(const V1_0::ActivityStatsInfo& info) {
+    const aidl::ActivityStatsTechSpecificInfo techSpecificInfo = {
+            .rat = AccessNetwork(AccessNetwork::UNKNOWN),
+            .frequencyRange = static_cast<int32_t>(
+                    aidl::ActivityStatsTechSpecificInfo::FREQUENCY_RANGE_UNKNOWN),
+            .txmModetimeMs = toAidl(info.txmModetimeMs),
+            .rxModeTimeMs = static_cast<int32_t>(info.rxModeTimeMs),
+    };
+
+    return {
+            .sleepModeTimeMs = static_cast<int32_t>(info.sleepModeTimeMs),
+            .idleModeTimeMs = static_cast<int32_t>(info.idleModeTimeMs),
+            .techSpecificInfo = {techSpecificInfo},
+    };
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/modem/structs.h b/radio/aidl/compat/libradiocompat/modem/structs.h
new file mode 100644
index 0000000..af714c7
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/modem/structs.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <aidl/android/hardware/radio/modem/ActivityStatsInfo.h>
+#include <aidl/android/hardware/radio/modem/ActivityStatsTechSpecificInfo.h>
+#include <aidl/android/hardware/radio/modem/HardwareConfig.h>
+#include <aidl/android/hardware/radio/modem/HardwareConfigModem.h>
+#include <aidl/android/hardware/radio/modem/HardwareConfigSim.h>
+#include <aidl/android/hardware/radio/modem/NvWriteItem.h>
+#include <aidl/android/hardware/radio/modem/RadioCapability.h>
+#include <android/hardware/radio/1.0/types.h>
+
+namespace android::hardware::radio::compat {
+
+V1_0::NvWriteItem toHidl(const ::aidl::android::hardware::radio::modem::NvWriteItem& item);
+
+::aidl::android::hardware::radio::modem::RadioCapability toAidl(const V1_0::RadioCapability& capa);
+V1_0::RadioCapability toHidl(const ::aidl::android::hardware::radio::modem::RadioCapability& capa);
+
+::aidl::android::hardware::radio::modem::HardwareConfig toAidl(const V1_0::HardwareConfig& config);
+
+::aidl::android::hardware::radio::modem::HardwareConfigModem  //
+toAidl(const V1_0::HardwareConfigModem& modem);
+
+::aidl::android::hardware::radio::modem::HardwareConfigSim toAidl(const V1_0::HardwareConfigSim& s);
+
+::aidl::android::hardware::radio::modem::ActivityStatsInfo toAidl(const V1_0::ActivityStatsInfo& i);
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/network/RadioIndication-network.cpp b/radio/aidl/compat/libradiocompat/network/RadioIndication-network.cpp
new file mode 100644
index 0000000..4eb99f7
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/network/RadioIndication-network.cpp
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libradiocompat/RadioIndication.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "NetworkIndication"
+
+namespace android::hardware::radio::compat {
+
+using ::aidl::android::hardware::radio::RadioTechnology;
+namespace aidl = ::aidl::android::hardware::radio::network;
+
+void RadioIndication::setResponseFunction(std::shared_ptr<aidl::IRadioNetworkIndication> netCb) {
+    mNetworkCb = netCb;
+}
+
+std::shared_ptr<aidl::IRadioNetworkIndication> RadioIndication::networkCb() {
+    return mNetworkCb.get();
+}
+
+Return<void> RadioIndication::barringInfoChanged(V1_0::RadioIndicationType type,
+                                                 const V1_5::CellIdentity& cellIdentity,
+                                                 const hidl_vec<V1_5::BarringInfo>& barringInfos) {
+    LOG_CALL << type;
+    networkCb()->barringInfoChanged(toAidl(type), toAidl(cellIdentity), toAidl(barringInfos));
+    return {};
+}
+
+Return<void> RadioIndication::cdmaPrlChanged(V1_0::RadioIndicationType type, int32_t version) {
+    LOG_CALL << type;
+    networkCb()->cdmaPrlChanged(toAidl(type), version);
+    return {};
+}
+
+Return<void> RadioIndication::cellInfoList(V1_0::RadioIndicationType type,
+                                           const hidl_vec<V1_0::CellInfo>&) {
+    LOG_CALL << type;
+    LOG(ERROR) << "IRadio HAL 1.0 not supported";
+    return {};
+}
+
+Return<void> RadioIndication::cellInfoList_1_2(V1_0::RadioIndicationType type,
+                                               const hidl_vec<V1_2::CellInfo>&) {
+    LOG_CALL << type;
+    LOG(ERROR) << "IRadio HAL 1.2 not supported";
+    return {};
+}
+
+Return<void> RadioIndication::cellInfoList_1_4(V1_0::RadioIndicationType type,
+                                               const hidl_vec<V1_4::CellInfo>&) {
+    LOG_CALL << type;
+    LOG(ERROR) << "IRadio HAL 1.4 not supported";
+    return {};
+}
+
+Return<void> RadioIndication::cellInfoList_1_5(V1_0::RadioIndicationType type,
+                                               const hidl_vec<V1_5::CellInfo>& records) {
+    LOG_CALL << type;
+    networkCb()->cellInfoList(toAidl(type), toAidl(records));
+    return {};
+}
+
+Return<void> RadioIndication::cellInfoList_1_6(V1_0::RadioIndicationType type,
+                                               const hidl_vec<V1_6::CellInfo>& records) {
+    LOG_CALL << type;
+    networkCb()->cellInfoList(toAidl(type), toAidl(records));
+    return {};
+}
+
+Return<void> RadioIndication::currentLinkCapacityEstimate(V1_0::RadioIndicationType type,
+                                                          const V1_2::LinkCapacityEstimate& lce) {
+    LOG_CALL << type;
+    networkCb()->currentLinkCapacityEstimate(toAidl(type), toAidl(lce));
+    return {};
+}
+
+Return<void> RadioIndication::currentLinkCapacityEstimate_1_6(
+        V1_0::RadioIndicationType type, const V1_6::LinkCapacityEstimate& lce) {
+    LOG_CALL << type;
+    networkCb()->currentLinkCapacityEstimate(toAidl(type), toAidl(lce));
+    return {};
+}
+
+Return<void> RadioIndication::currentPhysicalChannelConfigs(
+        V1_0::RadioIndicationType type, const hidl_vec<V1_2::PhysicalChannelConfig>&) {
+    LOG_CALL << type;
+    LOG(ERROR) << "IRadio HAL 1.0 not supported";
+    return {};
+}
+
+Return<void> RadioIndication::currentPhysicalChannelConfigs_1_4(
+        V1_0::RadioIndicationType type, const hidl_vec<V1_4::PhysicalChannelConfig>& configs) {
+    LOG_CALL << type;
+    networkCb()->currentPhysicalChannelConfigs(toAidl(type), toAidl(configs));
+    return {};
+}
+
+Return<void> RadioIndication::currentPhysicalChannelConfigs_1_6(
+        V1_0::RadioIndicationType type, const hidl_vec<V1_6::PhysicalChannelConfig>& configs) {
+    LOG_CALL << type;
+    networkCb()->currentPhysicalChannelConfigs(toAidl(type), toAidl(configs));
+    return {};
+}
+
+Return<void> RadioIndication::currentSignalStrength(V1_0::RadioIndicationType type,
+                                                    const V1_0::SignalStrength&) {
+    LOG_CALL << type;
+    LOG(ERROR) << "IRadio HAL 1.0 not supported";
+    return {};
+}
+
+Return<void> RadioIndication::currentSignalStrength_1_2(V1_0::RadioIndicationType type,
+                                                        const V1_2::SignalStrength&) {
+    LOG_CALL << type;
+    LOG(ERROR) << "IRadio HAL 1.2 not supported";
+    return {};
+}
+
+Return<void> RadioIndication::currentSignalStrength_1_4(
+        V1_0::RadioIndicationType type, const V1_4::SignalStrength& signalStrength) {
+    LOG_CALL << type;
+    networkCb()->currentSignalStrength(toAidl(type), toAidl(signalStrength));
+    return {};
+}
+
+Return<void> RadioIndication::currentSignalStrength_1_6(
+        V1_0::RadioIndicationType type, const V1_6::SignalStrength& signalStrength) {
+    LOG_CALL << type;
+    networkCb()->currentSignalStrength(toAidl(type), toAidl(signalStrength));
+    return {};
+}
+
+Return<void> RadioIndication::imsNetworkStateChanged(V1_0::RadioIndicationType type) {
+    LOG_CALL << type;
+    networkCb()->imsNetworkStateChanged(toAidl(type));
+    return {};
+}
+
+Return<void> RadioIndication::networkScanResult(V1_0::RadioIndicationType type,
+                                                const V1_1::NetworkScanResult&) {
+    LOG_CALL << type;
+    LOG(ERROR) << "IRadio HAL 1.0 not supported";
+    return {};
+}
+
+Return<void> RadioIndication::networkScanResult_1_2(V1_0::RadioIndicationType type,
+                                                    const V1_2::NetworkScanResult&) {
+    LOG_CALL << type;
+    LOG(ERROR) << "IRadio HAL 1.2 not supported";
+    return {};
+}
+
+Return<void> RadioIndication::networkScanResult_1_4(V1_0::RadioIndicationType type,
+                                                    const V1_4::NetworkScanResult&) {
+    LOG_CALL << type;
+    LOG(ERROR) << "IRadio HAL 1.4 not supported";
+    return {};
+}
+
+Return<void> RadioIndication::networkScanResult_1_5(V1_0::RadioIndicationType type,
+                                                    const V1_5::NetworkScanResult& result) {
+    LOG_CALL << type;
+    networkCb()->networkScanResult(toAidl(type), toAidl(result));
+    return {};
+}
+
+Return<void> RadioIndication::networkScanResult_1_6(V1_0::RadioIndicationType type,
+                                                    const V1_6::NetworkScanResult& result) {
+    LOG_CALL << type;
+    networkCb()->networkScanResult(toAidl(type), toAidl(result));
+    return {};
+}
+
+Return<void> RadioIndication::networkStateChanged(V1_0::RadioIndicationType type) {
+    LOG_CALL << type;
+    networkCb()->networkStateChanged(toAidl(type));
+    return {};
+}
+
+Return<void> RadioIndication::nitzTimeReceived(V1_0::RadioIndicationType type,
+                                               const hidl_string& nitzTime, uint64_t receivedTime) {
+    LOG_CALL << type;
+    networkCb()->nitzTimeReceived(toAidl(type), nitzTime, receivedTime, 0);
+    return {};
+}
+
+Return<void> RadioIndication::registrationFailed(  //
+        V1_0::RadioIndicationType type, const V1_5::CellIdentity& cellIdentity,
+        const hidl_string& chosenPlmn, hidl_bitfield<V1_5::Domain> domain, int32_t causeCode,
+        int32_t additionalCauseCode) {
+    LOG_CALL << type;
+    networkCb()->registrationFailed(toAidl(type), toAidl(cellIdentity), chosenPlmn, domain,
+                                    causeCode, additionalCauseCode);
+    return {};
+}
+
+Return<void> RadioIndication::restrictedStateChanged(V1_0::RadioIndicationType type,
+                                                     V1_0::PhoneRestrictedState state) {
+    LOG_CALL << type;
+    networkCb()->restrictedStateChanged(toAidl(type), aidl::PhoneRestrictedState(state));
+    return {};
+}
+
+Return<void> RadioIndication::suppSvcNotify(V1_0::RadioIndicationType type,
+                                            const V1_0::SuppSvcNotification& suppSvc) {
+    LOG_CALL << type;
+    networkCb()->suppSvcNotify(toAidl(type), toAidl(suppSvc));
+    return {};
+}
+
+Return<void> RadioIndication::voiceRadioTechChanged(V1_0::RadioIndicationType type,
+                                                    V1_0::RadioTechnology rat) {
+    LOG_CALL << type;
+    networkCb()->voiceRadioTechChanged(toAidl(type), RadioTechnology(rat));
+    return {};
+}
+
+Return<void> RadioIndication::lceData(V1_0::RadioIndicationType type, const V1_0::LceDataInfo&) {
+    LOG_CALL << type;
+    LOG(WARNING) << "lceData indication is deprecated";
+    return {};
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp b/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp
new file mode 100644
index 0000000..d5e2a8d
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libradiocompat/RadioNetwork.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+#include "utils.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "Network"
+
+namespace android::hardware::radio::compat {
+
+using ::aidl::android::hardware::radio::AccessNetwork;
+using ::ndk::ScopedAStatus;
+namespace aidl = ::aidl::android::hardware::radio::network;
+constexpr auto ok = &ScopedAStatus::ok;
+
+std::shared_ptr<aidl::IRadioNetworkResponse> RadioNetwork::respond() {
+    return mCallbackManager->response().networkCb();
+}
+
+ScopedAStatus RadioNetwork::getAllowedNetworkTypesBitmap(int32_t serial) {
+    LOG_CALL << serial;
+    if (mHal1_6) {
+        mHal1_6->getAllowedNetworkTypesBitmap(serial);
+    } else {
+        mHal1_5->getPreferredNetworkType(serial);
+    }
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::getAvailableBandModes(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getAvailableBandModes(serial);
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::getAvailableNetworks(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getAvailableNetworks(serial);
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::getBarringInfo(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getBarringInfo(serial);
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::getCdmaRoamingPreference(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getCdmaRoamingPreference(serial);
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::getCellInfoList(int32_t serial) {
+    LOG_CALL << serial;
+    if (mHal1_6) {
+        mHal1_6->getCellInfoList_1_6(serial);
+    } else {
+        mHal1_5->getCellInfoList(serial);
+    }
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::getDataRegistrationState(int32_t serial) {
+    LOG_CALL << serial;
+    if (mHal1_6) {
+        mHal1_6->getDataRegistrationState_1_6(serial);
+    } else {
+        mHal1_5->getDataRegistrationState_1_5(serial);
+    }
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::getImsRegistrationState(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getImsRegistrationState(serial);
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::getNetworkSelectionMode(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getNetworkSelectionMode(serial);
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::getOperator(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getOperator(serial);
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::getSignalStrength(int32_t serial) {
+    LOG_CALL << serial;
+    if (mHal1_6) {
+        mHal1_6->getSignalStrength_1_6(serial);
+    } else {
+        mHal1_5->getSignalStrength_1_4(serial);
+    }
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::getSystemSelectionChannels(int32_t serial) {
+    LOG_CALL << serial;
+    if (mHal1_6) {
+        mHal1_6->getSystemSelectionChannels(serial);
+    } else {
+        respond()->getSystemSelectionChannelsResponse(notSupported(serial), {});
+    }
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::getVoiceRadioTechnology(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getVoiceRadioTechnology(serial);
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::getVoiceRegistrationState(int32_t serial) {
+    LOG_CALL << serial;
+    if (mHal1_6) {
+        mHal1_6->getVoiceRegistrationState_1_6(serial);
+    } else {
+        mHal1_5->getVoiceRegistrationState_1_5(serial);
+    }
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::isNrDualConnectivityEnabled(int32_t serial) {
+    LOG_CALL << serial;
+    if (mHal1_6) {
+        mHal1_6->isNrDualConnectivityEnabled(serial);
+    } else {
+        respond()->isNrDualConnectivityEnabledResponse(notSupported(serial), false);
+    }
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::responseAcknowledgement() {
+    LOG_CALL;
+    mHal1_5->responseAcknowledgement();
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::setAllowedNetworkTypesBitmap(int32_t serial, int32_t ntype) {
+    LOG_CALL << serial;
+    const auto raf = toHidlBitfield<V1_4::RadioAccessFamily>(ntype);
+    if (mHal1_6) {
+        mHal1_6->setAllowedNetworkTypesBitmap(serial, raf);
+    } else {
+        mHal1_5->setPreferredNetworkType(serial, getNetworkTypeFromRaf(raf));
+    }
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::setBandMode(int32_t serial, aidl::RadioBandMode mode) {
+    LOG_CALL << serial;
+    mHal1_5->setBandMode(serial, V1_0::RadioBandMode(mode));
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::setBarringPassword(int32_t serial, const std::string& facility,
+                                               const std::string& oldPw, const std::string& newPw) {
+    LOG_CALL << serial;
+    mHal1_5->setBarringPassword(serial, facility, oldPw, newPw);
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::setCdmaRoamingPreference(int32_t serial, aidl::CdmaRoamingType type) {
+    LOG_CALL << serial;
+    mHal1_5->setCdmaRoamingPreference(serial, V1_0::CdmaRoamingType(type));
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::setCellInfoListRate(int32_t serial, int32_t rate) {
+    LOG_CALL << serial;
+    mHal1_5->setCellInfoListRate(serial, rate);
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::setIndicationFilter(int32_t serial, int32_t indFilter) {
+    LOG_CALL << serial;
+    mHal1_5->setIndicationFilter_1_5(serial, toHidlBitfield<V1_5::IndicationFilter>(indFilter));
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::setLinkCapacityReportingCriteria(  //
+        int32_t serial, int32_t hysteresisMs, int32_t hysteresisDlKbps, int32_t hysteresisUlKbps,
+        const std::vector<int32_t>& thrDownlinkKbps, const std::vector<int32_t>& thrUplinkKbps,
+        AccessNetwork accessNetwork) {
+    LOG_CALL << serial;
+    mHal1_5->setLinkCapacityReportingCriteria_1_5(  //
+            serial, hysteresisMs, hysteresisDlKbps, hysteresisUlKbps, thrDownlinkKbps,
+            thrUplinkKbps, V1_5::AccessNetwork(accessNetwork));
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::setLocationUpdates(int32_t serial, bool enable) {
+    LOG_CALL << serial;
+    mHal1_5->setLocationUpdates(serial, enable);
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::setNetworkSelectionModeAutomatic(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->setNetworkSelectionModeAutomatic(serial);
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::setNetworkSelectionModeManual(  //
+        int32_t serial, const std::string& opNumeric, AccessNetwork ran) {
+    LOG_CALL << serial;
+    mHal1_5->setNetworkSelectionModeManual_1_5(serial, opNumeric, toRadioAccessNetworks(ran));
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::setNrDualConnectivityState(int32_t serial,
+                                                       aidl::NrDualConnectivityState st) {
+    LOG_CALL << serial;
+    if (mHal1_6) {
+        mHal1_6->setNrDualConnectivityState(serial, V1_6::NrDualConnectivityState(st));
+    } else {
+        respond()->setNrDualConnectivityStateResponse(notSupported(serial));
+    }
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::setResponseFunctions(
+        const std::shared_ptr<aidl::IRadioNetworkResponse>& response,
+        const std::shared_ptr<aidl::IRadioNetworkIndication>& indication) {
+    LOG_CALL << response << ' ' << indication;
+    mCallbackManager->setResponseFunctions(response, indication);
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::setSignalStrengthReportingCriteria(
+        int32_t serial, const std::vector<aidl::SignalThresholdInfo>& infos) {
+    LOG_CALL << serial;
+    if (infos.size() == 0) {
+        LOG(ERROR) << "Threshold info array is empty - dropping setSignalStrengthReportingCriteria";
+        return ok();
+    }
+    if (infos.size() > 1) {
+        LOG(WARNING) << "Multi-element reporting criteria are not supported with HIDL HAL";
+    }
+    mHal1_5->setSignalStrengthReportingCriteria_1_5(serial, toHidl(infos[0]),
+                                                    V1_5::AccessNetwork(infos[0].ran));
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::setSuppServiceNotifications(int32_t serial, bool enable) {
+    LOG_CALL << serial;
+    mHal1_5->setSuppServiceNotifications(serial, enable);
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::setSystemSelectionChannels(  //
+        int32_t serial, bool specifyCh, const std::vector<aidl::RadioAccessSpecifier>& specifiers) {
+    LOG_CALL << serial;
+    mHal1_5->setSystemSelectionChannels_1_5(serial, specifyCh, toHidl(specifiers));
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::startNetworkScan(int32_t serial, const aidl::NetworkScanRequest& req) {
+    LOG_CALL << serial;
+    mHal1_5->startNetworkScan_1_5(serial, toHidl(req));
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::stopNetworkScan(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->stopNetworkScan(serial);
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::supplyNetworkDepersonalization(int32_t ser, const std::string& nPin) {
+    LOG_CALL << ser;
+    mHal1_5->supplyNetworkDepersonalization(ser, nPin);
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::setUsageSetting(int32_t serial, aidl::UsageSetting) {
+    LOG_CALL << serial;
+    LOG(ERROR) << "setUsageSetting is unsupported by HIDL HALs";
+    respond()->setUsageSettingResponse(notSupported(serial));
+    return ok();
+}
+
+ScopedAStatus RadioNetwork::getUsageSetting(int32_t serial) {
+    LOG_CALL << serial;
+    LOG(ERROR) << "getUsageSetting is unsupported by HIDL HALs";
+    respond()->getUsageSettingResponse(notSupported(serial), {});  // {} = neither voice nor data
+    return ok();
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/network/RadioResponse-network.cpp b/radio/aidl/compat/libradiocompat/network/RadioResponse-network.cpp
new file mode 100644
index 0000000..5a98eb2
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/network/RadioResponse-network.cpp
@@ -0,0 +1,461 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libradiocompat/RadioResponse.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+#include "utils.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "NetworkResponse"
+
+namespace android::hardware::radio::compat {
+
+using ::aidl::android::hardware::radio::RadioTechnology;
+using ::aidl::android::hardware::radio::RadioTechnologyFamily;
+namespace aidl = ::aidl::android::hardware::radio::network;
+
+void RadioResponse::setResponseFunction(std::shared_ptr<aidl::IRadioNetworkResponse> netCb) {
+    mNetworkCb = netCb;
+}
+
+std::shared_ptr<aidl::IRadioNetworkResponse> RadioResponse::networkCb() {
+    return mNetworkCb.get();
+}
+
+Return<void> RadioResponse::getAllowedNetworkTypesBitmapResponse(
+        const V1_6::RadioResponseInfo& info,
+        hidl_bitfield<V1_4::RadioAccessFamily> networkTypeBitmap) {
+    LOG_CALL << info.serial;
+    networkCb()->getAllowedNetworkTypesBitmapResponse(toAidl(info), networkTypeBitmap);
+    return {};
+}
+
+Return<void> RadioResponse::getPreferredNetworkTypeResponse(const V1_0::RadioResponseInfo& info,
+                                                            V1_0::PreferredNetworkType nwType) {
+    LOG_CALL << info.serial;
+    networkCb()->getAllowedNetworkTypesBitmapResponse(toAidl(info), getRafFromNetworkType(nwType));
+    return {};
+}
+
+Return<void> RadioResponse::getPreferredNetworkTypeBitmapResponse(
+        const V1_0::RadioResponseInfo& info, hidl_bitfield<V1_4::RadioAccessFamily>) {
+    LOG_CALL << info.serial;
+    LOG(ERROR) << "IRadio HAL 1.4 not supported";
+    return {};
+}
+
+Return<void> RadioResponse::getAvailableBandModesResponse(
+        const V1_0::RadioResponseInfo& info, const hidl_vec<V1_0::RadioBandMode>& bandModes) {
+    LOG_CALL << info.serial;
+    networkCb()->getAvailableBandModesResponse(toAidl(info), toAidl(bandModes));
+    return {};
+}
+
+Return<void> RadioResponse::getAvailableNetworksResponse(
+        const V1_0::RadioResponseInfo& info, const hidl_vec<V1_0::OperatorInfo>& networkInfos) {
+    LOG_CALL << info.serial;
+    networkCb()->getAvailableNetworksResponse(toAidl(info), toAidl(networkInfos));
+    return {};
+}
+
+Return<void> RadioResponse::getBarringInfoResponse(
+        const V1_0::RadioResponseInfo& info, const V1_5::CellIdentity& cellIdentity,
+        const hidl_vec<V1_5::BarringInfo>& barringInfos) {
+    LOG_CALL << info.serial;
+    networkCb()->getBarringInfoResponse(toAidl(info), toAidl(cellIdentity), toAidl(barringInfos));
+    return {};
+}
+
+Return<void> RadioResponse::getCdmaRoamingPreferenceResponse(const V1_0::RadioResponseInfo& info,
+                                                             V1_0::CdmaRoamingType type) {
+    LOG_CALL << info.serial;
+    networkCb()->getCdmaRoamingPreferenceResponse(toAidl(info), aidl::CdmaRoamingType(type));
+    return {};
+}
+
+Return<void> RadioResponse::getCellInfoListResponse(const V1_0::RadioResponseInfo& info,
+                                                    const hidl_vec<V1_0::CellInfo>&) {
+    LOG_CALL << info.serial;
+    LOG(ERROR) << "IRadio HAL 1.0 not supported";
+    return {};
+}
+
+Return<void> RadioResponse::getCellInfoListResponse_1_2(const V1_0::RadioResponseInfo& info,
+                                                        const hidl_vec<V1_2::CellInfo>&) {
+    LOG_CALL << info.serial;
+    LOG(ERROR) << "IRadio HAL 1.2 not supported";
+    return {};
+}
+
+Return<void> RadioResponse::getCellInfoListResponse_1_4(const V1_0::RadioResponseInfo& info,
+                                                        const hidl_vec<V1_4::CellInfo>&) {
+    LOG_CALL << info.serial;
+    LOG(ERROR) << "IRadio HAL 1.4 not supported";
+    return {};
+}
+
+Return<void> RadioResponse::getCellInfoListResponse_1_5(const V1_0::RadioResponseInfo& info,
+                                                        const hidl_vec<V1_5::CellInfo>& cellInfo) {
+    LOG_CALL << info.serial;
+    networkCb()->getCellInfoListResponse(toAidl(info), toAidl(cellInfo));
+    return {};
+}
+
+Return<void> RadioResponse::getCellInfoListResponse_1_6(const V1_6::RadioResponseInfo& info,
+                                                        const hidl_vec<V1_6::CellInfo>& cellInfo) {
+    LOG_CALL << info.serial;
+    networkCb()->getCellInfoListResponse(toAidl(info), toAidl(cellInfo));
+    return {};
+}
+
+Return<void> RadioResponse::getDataRegistrationStateResponse(const V1_0::RadioResponseInfo& info,
+                                                             const V1_0::DataRegStateResult&) {
+    LOG_CALL << info.serial;
+    LOG(ERROR) << "IRadio HAL 1.0 not supported";
+    return {};
+}
+
+Return<void> RadioResponse::getDataRegistrationStateResponse_1_2(
+        const V1_0::RadioResponseInfo& info, const V1_2::DataRegStateResult&) {
+    LOG_CALL << info.serial;
+    LOG(ERROR) << "IRadio HAL 1.2 not supported";
+    return {};
+}
+
+Return<void> RadioResponse::getDataRegistrationStateResponse_1_4(
+        const V1_0::RadioResponseInfo& info, const V1_4::DataRegStateResult&) {
+    LOG_CALL << info.serial;
+    LOG(ERROR) << "IRadio HAL 1.4 not supported";
+    return {};
+}
+
+Return<void> RadioResponse::getDataRegistrationStateResponse_1_5(
+        const V1_0::RadioResponseInfo& info, const V1_5::RegStateResult& dataRegResponse) {
+    LOG_CALL << info.serial;
+    networkCb()->getDataRegistrationStateResponse(toAidl(info), toAidl(dataRegResponse));
+    return {};
+}
+
+Return<void> RadioResponse::getDataRegistrationStateResponse_1_6(
+        const V1_6::RadioResponseInfo& info, const V1_6::RegStateResult& dataRegResponse) {
+    LOG_CALL << info.serial;
+    networkCb()->getDataRegistrationStateResponse(toAidl(info), toAidl(dataRegResponse));
+    return {};
+}
+
+Return<void> RadioResponse::getImsRegistrationStateResponse(  //
+        const V1_0::RadioResponseInfo& info, bool isRegd, V1_0::RadioTechnologyFamily ratFamily) {
+    LOG_CALL << info.serial;
+    networkCb()->getImsRegistrationStateResponse(toAidl(info), isRegd,
+                                                 RadioTechnologyFamily(ratFamily));
+    return {};
+}
+
+Return<void> RadioResponse::getNeighboringCidsResponse(const V1_0::RadioResponseInfo& info,
+                                                       const hidl_vec<V1_0::NeighboringCell>&) {
+    LOG_CALL << info.serial;
+    LOG(ERROR) << "getNeighboringCidsResponse is not supposed to be called";
+    return {};
+}
+
+Return<void> RadioResponse::getNetworkSelectionModeResponse(const V1_0::RadioResponseInfo& info,
+                                                            bool manual) {
+    LOG_CALL << info.serial;
+    networkCb()->getNetworkSelectionModeResponse(toAidl(info), manual);
+    return {};
+}
+
+Return<void> RadioResponse::getOperatorResponse(  //
+        const V1_0::RadioResponseInfo& info, const hidl_string& longName,
+        const hidl_string& shortName, const hidl_string& numeric) {
+    LOG_CALL << info.serial;
+    networkCb()->getOperatorResponse(toAidl(info), longName, shortName, numeric);
+    return {};
+}
+
+Return<void> RadioResponse::getSignalStrengthResponse(const V1_0::RadioResponseInfo& info,
+                                                      const V1_0::SignalStrength&) {
+    LOG_CALL << info.serial;
+    LOG(ERROR) << "IRadio HAL 1.0 not supported";
+    return {};
+}
+
+Return<void> RadioResponse::getSignalStrengthResponse_1_2(const V1_0::RadioResponseInfo& info,
+                                                          const V1_2::SignalStrength&) {
+    LOG_CALL << info.serial;
+    LOG(ERROR) << "IRadio HAL 1.2 not supported";
+    return {};
+}
+
+Return<void> RadioResponse::getSignalStrengthResponse_1_4(
+        const V1_0::RadioResponseInfo& info, const V1_4::SignalStrength& signalStrength) {
+    LOG_CALL << info.serial;
+    networkCb()->getSignalStrengthResponse(toAidl(info), toAidl(signalStrength));
+    return {};
+}
+
+Return<void> RadioResponse::getSignalStrengthResponse_1_6(
+        const V1_6::RadioResponseInfo& info, const V1_6::SignalStrength& signalStrength) {
+    LOG_CALL << info.serial;
+    networkCb()->getSignalStrengthResponse(toAidl(info), toAidl(signalStrength));
+    return {};
+}
+
+Return<void> RadioResponse::getSystemSelectionChannelsResponse(
+        const V1_6::RadioResponseInfo& info,
+        const hidl_vec<V1_5::RadioAccessSpecifier>& specifiers) {
+    LOG_CALL << info.serial;
+    networkCb()->getSystemSelectionChannelsResponse(toAidl(info), toAidl(specifiers));
+    return {};
+}
+
+Return<void> RadioResponse::getVoiceRadioTechnologyResponse(const V1_0::RadioResponseInfo& info,
+                                                            V1_0::RadioTechnology rat) {
+    LOG_CALL << info.serial;
+    networkCb()->getVoiceRadioTechnologyResponse(toAidl(info), RadioTechnology(rat));
+    return {};
+}
+
+Return<void> RadioResponse::getVoiceRegistrationStateResponse(const V1_0::RadioResponseInfo& info,
+                                                              const V1_0::VoiceRegStateResult&) {
+    LOG_CALL << info.serial;
+    LOG(ERROR) << "IRadio HAL 1.0 not supported";
+    return {};
+}
+
+Return<void> RadioResponse::getVoiceRegistrationStateResponse_1_2(
+        const V1_0::RadioResponseInfo& info, const V1_2::VoiceRegStateResult&) {
+    LOG_CALL << info.serial;
+    LOG(ERROR) << "IRadio HAL 1.2 not supported";
+    return {};
+}
+
+Return<void> RadioResponse::getVoiceRegistrationStateResponse_1_5(
+        const V1_0::RadioResponseInfo& info, const V1_5::RegStateResult& voiceRegResponse) {
+    LOG_CALL << info.serial;
+    networkCb()->getVoiceRegistrationStateResponse(toAidl(info), toAidl(voiceRegResponse));
+    return {};
+}
+
+Return<void> RadioResponse::getVoiceRegistrationStateResponse_1_6(
+        const V1_6::RadioResponseInfo& info, const V1_6::RegStateResult& voiceRegResponse) {
+    LOG_CALL << info.serial;
+    networkCb()->getVoiceRegistrationStateResponse(toAidl(info), toAidl(voiceRegResponse));
+    return {};
+}
+
+Return<void> RadioResponse::isNrDualConnectivityEnabledResponse(const V1_6::RadioResponseInfo& info,
+                                                                bool isEnabled) {
+    LOG_CALL << info.serial;
+    networkCb()->isNrDualConnectivityEnabledResponse(toAidl(info), isEnabled);
+    return {};
+}
+
+Return<void> RadioResponse::pullLceDataResponse(const V1_0::RadioResponseInfo& info,
+                                                const V1_0::LceDataInfo&) {
+    LOG_CALL << info.serial;
+    LOG(ERROR) << "pullLceDataResponse is not supposed to be called";
+    return {};
+}
+
+Return<void> RadioResponse::setAllowedNetworkTypesBitmapResponse(const V1_6::RadioResponseInfo& i) {
+    LOG_CALL << i.serial;
+    networkCb()->setAllowedNetworkTypesBitmapResponse(toAidl(i));
+    return {};
+}
+
+Return<void> RadioResponse::setPreferredNetworkTypeResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    networkCb()->setAllowedNetworkTypesBitmapResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setPreferredNetworkTypeBitmapResponse(
+        const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    LOG(ERROR) << "IRadio HAL 1.4 not supported";
+    return {};
+}
+
+Return<void> RadioResponse::setBandModeResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    networkCb()->setBandModeResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setBarringPasswordResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    networkCb()->setBarringPasswordResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setCdmaRoamingPreferenceResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    networkCb()->setCdmaRoamingPreferenceResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setCellInfoListRateResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    networkCb()->setCellInfoListRateResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setIndicationFilterResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    networkCb()->setIndicationFilterResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setIndicationFilterResponse_1_5(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    networkCb()->setIndicationFilterResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setLinkCapacityReportingCriteriaResponse(
+        const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    networkCb()->setLinkCapacityReportingCriteriaResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setLinkCapacityReportingCriteriaResponse_1_5(
+        const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    networkCb()->setLinkCapacityReportingCriteriaResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setLocationUpdatesResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    networkCb()->setLocationUpdatesResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setNetworkSelectionModeAutomaticResponse(
+        const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    networkCb()->setNetworkSelectionModeAutomaticResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setNetworkSelectionModeManualResponse(
+        const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    networkCb()->setNetworkSelectionModeManualResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setNetworkSelectionModeManualResponse_1_5(
+        const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    networkCb()->setNetworkSelectionModeManualResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setNrDualConnectivityStateResponse(
+        const V1_6::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    networkCb()->setNrDualConnectivityStateResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setSignalStrengthReportingCriteriaResponse(
+        const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    networkCb()->setSignalStrengthReportingCriteriaResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setSignalStrengthReportingCriteriaResponse_1_5(
+        const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    networkCb()->setSignalStrengthReportingCriteriaResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setSuppServiceNotificationsResponse(
+        const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    networkCb()->setSuppServiceNotificationsResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setSystemSelectionChannelsResponse(
+        const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    networkCb()->setSystemSelectionChannelsResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setSystemSelectionChannelsResponse_1_5(
+        const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    networkCb()->setSystemSelectionChannelsResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::startNetworkScanResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    networkCb()->startNetworkScanResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::startNetworkScanResponse_1_4(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    networkCb()->startNetworkScanResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::startNetworkScanResponse_1_5(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    networkCb()->startNetworkScanResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::stopNetworkScanResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    networkCb()->stopNetworkScanResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::supplyNetworkDepersonalizationResponse(
+        const V1_0::RadioResponseInfo& info, int32_t remainingRetries) {
+    LOG_CALL << info.serial;
+    networkCb()->supplyNetworkDepersonalizationResponse(toAidl(info), remainingRetries);
+    return {};
+}
+
+Return<void> RadioResponse::startLceServiceResponse(const V1_0::RadioResponseInfo& info,
+                                                    const V1_0::LceStatusInfo&) {
+    LOG_CALL << info.serial;
+    LOG(WARNING) << "startLceServiceResponse is deprecated";
+    return {};
+}
+
+Return<void> RadioResponse::stopLceServiceResponse(const V1_0::RadioResponseInfo& info,
+                                                   const V1_0::LceStatusInfo&) {
+    LOG_CALL << info.serial;
+    LOG(WARNING) << "stopLceServiceResponse is deprecated";
+    return {};
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/network/structs.cpp b/radio/aidl/compat/libradiocompat/network/structs.cpp
new file mode 100644
index 0000000..d0b3b90
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/network/structs.cpp
@@ -0,0 +1,700 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "structs.h"
+
+#include "commonStructs.h"
+
+#include "collections.h"
+
+#include <android-base/logging.h>
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::network;
+using ::aidl::android::hardware::radio::AccessNetwork;
+using ::aidl::android::hardware::radio::RadioTechnology;
+
+aidl::RadioBandMode toAidl(V1_0::RadioBandMode mode) {
+    return aidl::RadioBandMode(mode);
+}
+
+aidl::GeranBands toAidl(V1_1::GeranBands band) {
+    return aidl::GeranBands(band);
+}
+
+V1_1::GeranBands toHidl(aidl::GeranBands band) {
+    return V1_1::GeranBands(band);
+}
+
+aidl::UtranBands toAidl(V1_5::UtranBands band) {
+    return aidl::UtranBands(band);
+}
+
+V1_5::UtranBands toHidl(aidl::UtranBands band) {
+    return V1_5::UtranBands(band);
+}
+
+aidl::EutranBands toAidl(V1_5::EutranBands band) {
+    return aidl::EutranBands(band);
+}
+
+V1_5::EutranBands toHidl(aidl::EutranBands band) {
+    return V1_5::EutranBands(band);
+}
+
+aidl::NgranBands toAidl(V1_5::NgranBands band) {
+    return aidl::NgranBands(band);
+}
+
+V1_5::NgranBands toHidl(aidl::NgranBands band) {
+    return V1_5::NgranBands(band);
+}
+
+V1_5::SignalThresholdInfo toHidl(const aidl::SignalThresholdInfo& info) {
+    return {
+            .signalMeasurement = V1_5::SignalMeasurementType{info.signalMeasurement},
+            .hysteresisMs = info.hysteresisMs,
+            .hysteresisDb = info.hysteresisDb,
+            .thresholds = info.thresholds,
+            .isEnabled = info.isEnabled,
+    };
+}
+
+static aidl::RadioAccessSpecifierBands toAidl(const V1_5::RadioAccessSpecifier::Bands& bands) {
+    using Discr = V1_5::RadioAccessSpecifier::Bands::hidl_discriminator;
+    const auto discr = bands.getDiscriminator();
+
+    if (discr == Discr::geranBands) return toAidl(bands.geranBands());
+    if (discr == Discr::utranBands) return toAidl(bands.utranBands());
+    if (discr == Discr::eutranBands) return toAidl(bands.eutranBands());
+    if (discr == Discr::ngranBands) return toAidl(bands.ngranBands());
+
+    return {};
+}
+
+static V1_5::RadioAccessSpecifier::Bands toHidl(const aidl::RadioAccessSpecifierBands& bands) {
+    V1_5::RadioAccessSpecifier::Bands hidl;
+    using Tag = aidl::RadioAccessSpecifierBands::Tag;
+
+    if (bands.getTag() == Tag::geranBands) hidl.geranBands(toHidl(bands.get<Tag::geranBands>()));
+    if (bands.getTag() == Tag::utranBands) hidl.utranBands(toHidl(bands.get<Tag::utranBands>()));
+    if (bands.getTag() == Tag::eutranBands) hidl.eutranBands(toHidl(bands.get<Tag::eutranBands>()));
+    if (bands.getTag() == Tag::ngranBands) hidl.ngranBands(toHidl(bands.get<Tag::ngranBands>()));
+
+    return hidl;
+}
+
+AccessNetwork fromRadioAccessNetwork(V1_5::RadioAccessNetworks ran) {
+    switch (ran) {
+        case V1_5::RadioAccessNetworks::UNKNOWN:
+            return AccessNetwork::UNKNOWN;
+        case V1_5::RadioAccessNetworks::GERAN:
+            return AccessNetwork::GERAN;
+        case V1_5::RadioAccessNetworks::UTRAN:
+            return AccessNetwork::UTRAN;
+        case V1_5::RadioAccessNetworks::EUTRAN:
+            return AccessNetwork::EUTRAN;
+        case V1_5::RadioAccessNetworks::CDMA2000:
+            return AccessNetwork::CDMA2000;
+        case V1_5::RadioAccessNetworks::NGRAN:
+            return AccessNetwork::NGRAN;
+        default:
+            return AccessNetwork::UNKNOWN;
+    }
+}
+
+aidl::RadioAccessSpecifier toAidl(const V1_5::RadioAccessSpecifier& spec) {
+    return {
+            .accessNetwork = fromRadioAccessNetwork(spec.radioAccessNetwork),
+            .bands = toAidl(spec.bands),
+            .channels = spec.channels,
+    };
+}
+
+V1_5::RadioAccessNetworks toRadioAccessNetworks(AccessNetwork val) {
+    switch (val) {
+        case AccessNetwork::UNKNOWN:
+            return V1_5::RadioAccessNetworks::UNKNOWN;
+        case AccessNetwork::GERAN:
+            return V1_5::RadioAccessNetworks::GERAN;
+        case AccessNetwork::UTRAN:
+            return V1_5::RadioAccessNetworks::UTRAN;
+        case AccessNetwork::EUTRAN:
+            return V1_5::RadioAccessNetworks::EUTRAN;
+        case AccessNetwork::CDMA2000:
+            return V1_5::RadioAccessNetworks::CDMA2000;
+        case AccessNetwork::NGRAN:
+            return V1_5::RadioAccessNetworks::NGRAN;
+        case AccessNetwork::IWLAN:
+        default:
+            return V1_5::RadioAccessNetworks::UNKNOWN;
+    }
+}
+
+V1_5::RadioAccessSpecifier toHidl(const aidl::RadioAccessSpecifier& spec) {
+    return {
+            .radioAccessNetwork = toRadioAccessNetworks(spec.accessNetwork),
+            .bands = toHidl(spec.bands),
+            .channels = spec.channels,
+    };
+}
+
+V1_5::NetworkScanRequest toHidl(const aidl::NetworkScanRequest& req) {
+    return {
+            .type = V1_1::ScanType{req.type},
+            .interval = req.interval,
+            .specifiers = toHidl(req.specifiers),
+            .maxSearchTime = req.maxSearchTime,
+            .incrementalResults = req.incrementalResults,
+            .incrementalResultsPeriodicity = req.incrementalResultsPeriodicity,
+            .mccMncs = toHidl(req.mccMncs),
+    };
+}
+
+static aidl::OperatorInfo toAidl(const V1_2::CellIdentityOperatorNames& names) {
+    return {
+            .alphaLong = names.alphaLong,
+            .alphaShort = names.alphaShort,
+            .operatorNumeric = "",
+            .status = aidl::OperatorInfo::STATUS_UNKNOWN,
+    };
+}
+
+static aidl::CellIdentityGsm toAidl(const V1_5::CellIdentityGsm& ci) {
+    return {
+            .mcc = ci.base.base.mcc,
+            .mnc = ci.base.base.mnc,
+            .lac = ci.base.base.lac,
+            .cid = ci.base.base.cid,
+            .arfcn = ci.base.base.arfcn,
+            .bsic = static_cast<int8_t>(ci.base.base.bsic),
+            .operatorNames = toAidl(ci.base.operatorNames),
+            .additionalPlmns = toAidl(ci.additionalPlmns),
+    };
+}
+
+aidl::ClosedSubscriberGroupInfo toAidl(const V1_5::ClosedSubscriberGroupInfo& info) {
+    return {
+            .csgIndication = info.csgIndication,
+            .homeNodebName = info.homeNodebName,
+            .csgIdentity = info.csgIdentity,
+    };
+}
+
+static std::optional<aidl::ClosedSubscriberGroupInfo> toAidl(const V1_5::OptionalCsgInfo& opt) {
+    using descr = V1_5::OptionalCsgInfo::hidl_discriminator;
+    if (opt.getDiscriminator() == descr::noinit) return std::nullopt;
+    return toAidl(opt.csgInfo());
+}
+
+static aidl::CellIdentityWcdma toAidl(const V1_5::CellIdentityWcdma& ci) {
+    return {
+            .mcc = ci.base.base.mcc,
+            .mnc = ci.base.base.mnc,
+            .lac = ci.base.base.lac,
+            .cid = ci.base.base.cid,
+            .psc = ci.base.base.psc,
+            .uarfcn = ci.base.base.uarfcn,
+            .operatorNames = toAidl(ci.base.operatorNames),
+            .additionalPlmns = toAidl(ci.additionalPlmns),
+            .csgInfo = toAidl(ci.optionalCsgInfo),
+    };
+}
+
+static aidl::CellIdentityTdscdma toAidl(const V1_5::CellIdentityTdscdma& ci) {
+    return {
+            .mcc = ci.base.base.mcc,
+            .mnc = ci.base.base.mnc,
+            .lac = ci.base.base.lac,
+            .cid = ci.base.base.cid,
+            .cpid = ci.base.base.cpid,
+            .uarfcn = ci.base.uarfcn,
+            .operatorNames = toAidl(ci.base.operatorNames),
+            .additionalPlmns = toAidl(ci.additionalPlmns),
+            .csgInfo = toAidl(ci.optionalCsgInfo),
+    };
+}
+
+static aidl::CellIdentityCdma toAidl(const V1_2::CellIdentityCdma& ci) {
+    return {
+            .networkId = ci.base.networkId,
+            .systemId = ci.base.systemId,
+            .baseStationId = ci.base.baseStationId,
+            .longitude = ci.base.longitude,
+            .latitude = ci.base.latitude,
+            .operatorNames = toAidl(ci.operatorNames),
+    };
+}
+
+static aidl::CellIdentityLte toAidl(const V1_5::CellIdentityLte& ci) {
+    return {
+            .mcc = ci.base.base.mcc,
+            .mnc = ci.base.base.mnc,
+            .ci = ci.base.base.ci,
+            .pci = ci.base.base.pci,
+            .tac = ci.base.base.tac,
+            .earfcn = ci.base.base.earfcn,
+            .operatorNames = toAidl(ci.base.operatorNames),
+            .bandwidth = ci.base.bandwidth,
+            .additionalPlmns = toAidl(ci.additionalPlmns),
+            .csgInfo = toAidl(ci.optionalCsgInfo),
+            .bands = toAidl(ci.bands),
+    };
+}
+
+static aidl::CellIdentityNr toAidl(const V1_5::CellIdentityNr& ci) {
+    return {
+            .mcc = ci.base.mcc,
+            .mnc = ci.base.mnc,
+            .nci = static_cast<int64_t>(ci.base.nci),
+            .pci = static_cast<int32_t>(ci.base.pci),
+            .tac = ci.base.tac,
+            .nrarfcn = ci.base.nrarfcn,
+            .operatorNames = toAidl(ci.base.operatorNames),
+            .additionalPlmns = toAidl(ci.additionalPlmns),
+            .bands = toAidl(ci.bands),
+    };
+}
+
+aidl::CellIdentity toAidl(const V1_5::CellIdentity& ci) {
+    using Discr = V1_5::CellIdentity::hidl_discriminator;
+    const auto discr = ci.getDiscriminator();
+
+    if (discr == Discr::gsm) return toAidl(ci.gsm());
+    if (discr == Discr::wcdma) return toAidl(ci.wcdma());
+    if (discr == Discr::tdscdma) return toAidl(ci.tdscdma());
+    if (discr == Discr::cdma) return toAidl(ci.cdma());
+    if (discr == Discr::lte) return toAidl(ci.lte());
+    if (discr == Discr::nr) return toAidl(ci.nr());
+
+    return {};
+}
+
+static std::optional<aidl::BarringTypeSpecificInfo>  //
+toAidl(const V1_5::BarringInfo::BarringTypeSpecificInfo& opt) {
+    using discr = V1_5::BarringInfo::BarringTypeSpecificInfo::hidl_discriminator;
+    if (opt.getDiscriminator() == discr::noinit) return std::nullopt;
+
+    const auto& info = opt.conditional();
+    return aidl::BarringTypeSpecificInfo{
+            .factor = info.factor,
+            .timeSeconds = info.timeSeconds,
+            .isBarred = info.isBarred,
+    };
+}
+
+aidl::BarringInfo toAidl(const V1_5::BarringInfo& info) {
+    return {
+            .serviceType = static_cast<int32_t>(info.serviceType),
+            .barringType = static_cast<int32_t>(info.barringType),
+            .barringTypeSpecificInfo = toAidl(info.barringTypeSpecificInfo),
+    };
+}
+
+static aidl::GsmSignalStrength toAidl(const V1_0::GsmSignalStrength& sig) {
+    return {
+            .signalStrength = static_cast<int32_t>(sig.signalStrength),
+            .bitErrorRate = static_cast<int32_t>(sig.bitErrorRate),
+            .timingAdvance = sig.timingAdvance,
+    };
+}
+
+static aidl::CellInfoGsm toAidl(const V1_5::CellInfoGsm& info) {
+    return {
+            .cellIdentityGsm = toAidl(info.cellIdentityGsm),
+            .signalStrengthGsm = toAidl(info.signalStrengthGsm),
+    };
+}
+
+static aidl::WcdmaSignalStrength toAidl(const V1_2::WcdmaSignalStrength& sig) {
+    return {
+            .signalStrength = sig.base.signalStrength,
+            .bitErrorRate = sig.base.bitErrorRate,
+            .rscp = static_cast<int32_t>(sig.rscp),
+            .ecno = static_cast<int32_t>(sig.ecno),
+    };
+}
+
+static aidl::CellInfoWcdma toAidl(const V1_5::CellInfoWcdma& info) {
+    return {
+            .cellIdentityWcdma = toAidl(info.cellIdentityWcdma),
+            .signalStrengthWcdma = toAidl(info.signalStrengthWcdma),
+    };
+}
+
+static aidl::TdscdmaSignalStrength toAidl(const V1_2::TdscdmaSignalStrength& sig) {
+    return {
+            .signalStrength = static_cast<int32_t>(sig.signalStrength),
+            .bitErrorRate = static_cast<int32_t>(sig.bitErrorRate),
+            .rscp = static_cast<int32_t>(sig.rscp),
+    };
+}
+
+static aidl::CellInfoTdscdma toAidl(const V1_5::CellInfoTdscdma& info) {
+    return {
+            .cellIdentityTdscdma = toAidl(info.cellIdentityTdscdma),
+            .signalStrengthTdscdma = toAidl(info.signalStrengthTdscdma),
+    };
+}
+
+static aidl::LteSignalStrength toAidl(const V1_6::LteSignalStrength& sig) {
+    return {
+            .signalStrength = static_cast<int32_t>(sig.base.signalStrength),
+            .rsrp = static_cast<int32_t>(sig.base.rsrp),
+            .rsrq = static_cast<int32_t>(sig.base.rsrq),
+            .rssnr = sig.base.rssnr,
+            .cqi = static_cast<int32_t>(sig.base.cqi),
+            .timingAdvance = static_cast<int32_t>(sig.base.timingAdvance),
+            .cqiTableIndex = static_cast<int32_t>(sig.cqiTableIndex),
+    };
+}
+
+static aidl::LteSignalStrength toAidl(const V1_0::LteSignalStrength& sig) {
+    return toAidl({sig, 0});
+}
+
+static aidl::CellInfoLte toAidl(const V1_5::CellInfoLte& info) {
+    return {
+            .cellIdentityLte = toAidl(info.cellIdentityLte),
+            .signalStrengthLte = toAidl(info.signalStrengthLte),
+    };
+}
+
+static aidl::CellInfoLte toAidl(const V1_6::CellInfoLte& info) {
+    return {
+            .cellIdentityLte = toAidl(info.cellIdentityLte),
+            .signalStrengthLte = toAidl(info.signalStrengthLte),
+    };
+}
+
+static aidl::NrSignalStrength toAidl(const V1_6::NrSignalStrength& sig) {
+    return {
+            .ssRsrp = sig.base.ssRsrp,
+            .ssRsrq = sig.base.ssRsrq,
+            .ssSinr = sig.base.ssSinr,
+            .csiRsrp = sig.base.csiRsrp,
+            .csiRsrq = sig.base.csiRsrq,
+            .csiSinr = sig.base.csiSinr,
+            .csiCqiTableIndex = static_cast<int32_t>(sig.csiCqiTableIndex),
+            .csiCqiReport = sig.csiCqiReport,
+    };
+}
+
+static aidl::NrSignalStrength toAidl(const V1_4::NrSignalStrength& sig) {
+    return toAidl({sig, 0, 0});
+}
+
+static aidl::CellInfoNr toAidl(const V1_5::CellInfoNr& info) {
+    return {
+            .cellIdentityNr = toAidl(info.cellIdentityNr),
+            .signalStrengthNr = toAidl(info.signalStrengthNr),
+    };
+}
+
+static aidl::CellInfoNr toAidl(const V1_6::CellInfoNr& info) {
+    return {
+            .cellIdentityNr = toAidl(info.cellIdentityNr),
+            .signalStrengthNr = toAidl(info.signalStrengthNr),
+    };
+}
+
+static aidl::CdmaSignalStrength toAidl(const V1_0::CdmaSignalStrength& sig) {
+    return {
+            .dbm = static_cast<int32_t>(sig.dbm),
+            .ecio = static_cast<int32_t>(sig.ecio),
+    };
+}
+
+static aidl::EvdoSignalStrength toAidl(const V1_0::EvdoSignalStrength& sig) {
+    return {
+            .dbm = static_cast<int32_t>(sig.dbm),
+            .ecio = static_cast<int32_t>(sig.ecio),
+            .signalNoiseRatio = static_cast<int32_t>(sig.signalNoiseRatio),
+    };
+}
+
+static aidl::CellInfoCdma toAidl(const V1_2::CellInfoCdma& info) {
+    return {
+            .cellIdentityCdma = toAidl(info.cellIdentityCdma),
+            .signalStrengthCdma = toAidl(info.signalStrengthCdma),
+            .signalStrengthEvdo = toAidl(info.signalStrengthEvdo),
+    };
+}
+
+static aidl::CellInfoRatSpecificInfo toAidl(const V1_5::CellInfo::CellInfoRatSpecificInfo& ci) {
+    using Discr = V1_5::CellInfo::CellInfoRatSpecificInfo::hidl_discriminator;
+    const auto discr = ci.getDiscriminator();
+
+    if (discr == Discr::gsm) return toAidl(ci.gsm());
+    if (discr == Discr::wcdma) return toAidl(ci.wcdma());
+    if (discr == Discr::tdscdma) return toAidl(ci.tdscdma());
+    if (discr == Discr::lte) return toAidl(ci.lte());
+    if (discr == Discr::nr) return toAidl(ci.nr());
+    if (discr == Discr::cdma) return toAidl(ci.cdma());
+
+    return {};
+}
+
+static aidl::CellInfoRatSpecificInfo toAidl(const V1_6::CellInfo::CellInfoRatSpecificInfo& ci) {
+    using Discr = V1_6::CellInfo::CellInfoRatSpecificInfo::hidl_discriminator;
+    const auto discr = ci.getDiscriminator();
+
+    if (discr == Discr::gsm) return toAidl(ci.gsm());
+    if (discr == Discr::wcdma) return toAidl(ci.wcdma());
+    if (discr == Discr::tdscdma) return toAidl(ci.tdscdma());
+    if (discr == Discr::lte) return toAidl(ci.lte());
+    if (discr == Discr::nr) return toAidl(ci.nr());
+    if (discr == Discr::cdma) return toAidl(ci.cdma());
+
+    return {};
+}
+
+aidl::CellInfo toAidl(const V1_5::CellInfo& info) {
+    return {
+            .registered = info.registered,
+            // ignored: timeStampType and timeStamp
+            .connectionStatus = aidl::CellConnectionStatus(info.connectionStatus),
+            .ratSpecificInfo = toAidl(info.ratSpecificInfo),
+    };
+}
+
+aidl::CellInfo toAidl(const V1_6::CellInfo& info) {
+    return {
+            .registered = info.registered,
+            .connectionStatus = aidl::CellConnectionStatus(info.connectionStatus),
+            .ratSpecificInfo = toAidl(info.ratSpecificInfo),
+    };
+}
+
+aidl::LinkCapacityEstimate toAidl(const V1_2::LinkCapacityEstimate& e) {
+    return {
+            .downlinkCapacityKbps = static_cast<int32_t>(e.downlinkCapacityKbps),
+            .uplinkCapacityKbps = static_cast<int32_t>(e.uplinkCapacityKbps),
+    };
+}
+
+aidl::LinkCapacityEstimate toAidl(const V1_6::LinkCapacityEstimate& e) {
+    return {
+            .downlinkCapacityKbps = static_cast<int32_t>(e.downlinkCapacityKbps),
+            .uplinkCapacityKbps = static_cast<int32_t>(e.uplinkCapacityKbps),
+            .secondaryDownlinkCapacityKbps = static_cast<int32_t>(e.secondaryDownlinkCapacityKbps),
+            .secondaryUplinkCapacityKbps = static_cast<int32_t>(e.secondaryUplinkCapacityKbps),
+    };
+}
+
+static aidl::PhysicalChannelConfigBand toAidl(const V1_6::PhysicalChannelConfig::Band& band) {
+    using Discr = V1_6::PhysicalChannelConfig::Band::hidl_discriminator;
+    const auto discr = band.getDiscriminator();
+
+    if (discr == Discr::geranBand) return aidl::GeranBands(band.geranBand());
+    if (discr == Discr::utranBand) return aidl::UtranBands(band.utranBand());
+    if (discr == Discr::eutranBand) return aidl::EutranBands(band.eutranBand());
+    if (discr == Discr::ngranBand) return aidl::NgranBands(band.ngranBand());
+
+    return {};
+}
+
+aidl::PhysicalChannelConfig toAidl(const V1_4::PhysicalChannelConfig& cfg) {
+    int32_t downlinkChannelNumber = 0;
+    // ignored rfInfo.range
+    using Discr = V1_4::RadioFrequencyInfo::hidl_discriminator;
+    if (cfg.rfInfo.getDiscriminator() == Discr::channelNumber) {
+        downlinkChannelNumber = cfg.rfInfo.channelNumber();
+    }
+
+    return {
+            .status = aidl::CellConnectionStatus(cfg.base.status),
+            .rat = RadioTechnology(cfg.rat),
+            .downlinkChannelNumber = downlinkChannelNumber,
+            .cellBandwidthDownlinkKhz = cfg.base.cellBandwidthDownlink,
+            .contextIds = cfg.contextIds,
+            .physicalCellId = static_cast<int32_t>(cfg.physicalCellId),
+    };
+}
+
+aidl::PhysicalChannelConfig toAidl(const V1_6::PhysicalChannelConfig& cfg) {
+    return {
+            .status = aidl::CellConnectionStatus(cfg.status),
+            .rat = RadioTechnology(cfg.rat),
+            .downlinkChannelNumber = cfg.downlinkChannelNumber,
+            .uplinkChannelNumber = cfg.uplinkChannelNumber,
+            .cellBandwidthDownlinkKhz = cfg.cellBandwidthDownlinkKhz,
+            .cellBandwidthUplinkKhz = cfg.cellBandwidthUplinkKhz,
+            .contextIds = cfg.contextIds,
+            .physicalCellId = static_cast<int32_t>(cfg.physicalCellId),
+            .band = toAidl(cfg.band),
+    };
+}
+
+aidl::SignalStrength toAidl(const V1_4::SignalStrength& sig) {
+    return {
+            .gsm = toAidl(sig.gsm),
+            .cdma = toAidl(sig.cdma),
+            .evdo = toAidl(sig.evdo),
+            .lte = toAidl(sig.lte),
+            .tdscdma = toAidl(sig.tdscdma),
+            .wcdma = toAidl(sig.wcdma),
+            .nr = toAidl(sig.nr),
+    };
+}
+
+aidl::SignalStrength toAidl(const V1_6::SignalStrength& sig) {
+    return {
+            .gsm = toAidl(sig.gsm),
+            .cdma = toAidl(sig.cdma),
+            .evdo = toAidl(sig.evdo),
+            .lte = toAidl(sig.lte),
+            .tdscdma = toAidl(sig.tdscdma),
+            .wcdma = toAidl(sig.wcdma),
+            .nr = toAidl(sig.nr),
+    };
+}
+
+aidl::NetworkScanResult toAidl(const V1_5::NetworkScanResult& res) {
+    return {
+            .status = static_cast<int32_t>(res.status),
+            .error = toAidl(res.error),
+            .networkInfos = toAidl(res.networkInfos),
+    };
+}
+
+aidl::NetworkScanResult toAidl(const V1_6::NetworkScanResult& res) {
+    return {
+            .status = static_cast<int32_t>(res.status),
+            .error = toAidl(res.error),
+            .networkInfos = toAidl(res.networkInfos),
+    };
+}
+
+aidl::SuppSvcNotification toAidl(const V1_0::SuppSvcNotification& svc) {
+    return {
+            .isMT = svc.isMT,
+            .code = svc.code,
+            .index = svc.index,
+            .type = svc.type,
+            .number = svc.number,
+    };
+}
+
+aidl::OperatorInfo toAidl(const V1_0::OperatorInfo& info) {
+    return {
+            .alphaLong = info.alphaLong,
+            .alphaShort = info.alphaShort,
+            .operatorNumeric = info.operatorNumeric,
+            .status = static_cast<int32_t>(info.status),
+    };
+}
+
+static aidl::Cdma2000RegistrationInfo  //
+toAidl(const V1_5::RegStateResult::AccessTechnologySpecificInfo::Cdma2000RegistrationInfo& info) {
+    return {
+            .cssSupported = info.cssSupported,
+            .roamingIndicator = info.roamingIndicator,
+            .systemIsInPrl = static_cast<int32_t>(info.systemIsInPrl),
+            .defaultRoamingIndicator = info.defaultRoamingIndicator,
+    };
+}
+
+static aidl::LteVopsInfo toAidl(const V1_4::LteVopsInfo& info) {
+    return {
+            .isVopsSupported = info.isVopsSupported,
+            .isEmcBearerSupported = info.isEmcBearerSupported,
+    };
+}
+
+static aidl::NrIndicators toAidl(const V1_4::NrIndicators& info) {
+    return {
+            .isEndcAvailable = info.isEndcAvailable,
+            .isDcNrRestricted = info.isDcNrRestricted,
+            .isNrAvailable = info.isNrAvailable,
+    };
+}
+
+static aidl::EutranRegistrationInfo  //
+toAidl(const V1_5::RegStateResult::AccessTechnologySpecificInfo::EutranRegistrationInfo& info) {
+    return {
+            .lteVopsInfo = toAidl(info.lteVopsInfo),
+            .nrIndicators = toAidl(info.nrIndicators),
+    };
+}
+
+static aidl::NrVopsInfo toAidl(const V1_6::NrVopsInfo& info) {
+    return {
+            .vopsSupported = static_cast<int8_t>(info.vopsSupported),
+            .emcSupported = static_cast<int8_t>(info.emcSupported),
+            .emfSupported = static_cast<int8_t>(info.emfSupported),
+    };
+}
+
+static aidl::AccessTechnologySpecificInfo  //
+toAidl(const V1_5::RegStateResult::AccessTechnologySpecificInfo& info) {
+    using Discr = V1_5::RegStateResult::AccessTechnologySpecificInfo::hidl_discriminator;
+    const auto discr = info.getDiscriminator();
+
+    if (discr == Discr::cdmaInfo) return toAidl(info.cdmaInfo());
+    if (discr == Discr::eutranInfo) return toAidl(info.eutranInfo());
+
+    return {};
+}
+
+static aidl::AccessTechnologySpecificInfo  //
+toAidl(const V1_6::RegStateResult::AccessTechnologySpecificInfo& info) {
+    using Discr = V1_6::RegStateResult::AccessTechnologySpecificInfo::hidl_discriminator;
+    const auto discr = info.getDiscriminator();
+
+    if (discr == Discr::cdmaInfo) return toAidl(info.cdmaInfo());
+    if (discr == Discr::eutranInfo) return toAidl(info.eutranInfo());
+    if (discr == Discr::ngranNrVopsInfo) return toAidl(info.ngranNrVopsInfo());
+    if (discr == Discr::geranDtmSupported) {
+        using T = aidl::AccessTechnologySpecificInfo;
+        return T::make<T::Tag::geranDtmSupported>(info.geranDtmSupported());
+    }
+
+    return {};
+}
+
+aidl::RegStateResult toAidl(const V1_5::RegStateResult& res) {
+    return {
+            .regState = aidl::RegState(res.regState),
+            .rat = RadioTechnology(res.rat),
+            .reasonForDenial = aidl::RegistrationFailCause(res.reasonForDenial),
+            .cellIdentity = toAidl(res.cellIdentity),
+            .registeredPlmn = res.registeredPlmn,
+            .accessTechnologySpecificInfo = toAidl(res.accessTechnologySpecificInfo),
+    };
+}
+
+aidl::RegStateResult toAidl(const V1_6::RegStateResult& res) {
+    return {
+            .regState = aidl::RegState(res.regState),
+            .rat = RadioTechnology(res.rat),
+            .reasonForDenial = aidl::RegistrationFailCause(res.reasonForDenial),
+            .cellIdentity = toAidl(res.cellIdentity),
+            .registeredPlmn = res.registeredPlmn,
+            .accessTechnologySpecificInfo = toAidl(res.accessTechnologySpecificInfo),
+    };
+}
+
+aidl::LceDataInfo toAidl(const V1_0::LceDataInfo& info) {
+    return {
+            .lastHopCapacityKbps = static_cast<int32_t>(info.lastHopCapacityKbps),
+            .confidenceLevel = static_cast<int8_t>(info.confidenceLevel),
+            .lceSuspended = info.lceSuspended,
+    };
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/network/structs.h b/radio/aidl/compat/libradiocompat/network/structs.h
new file mode 100644
index 0000000..6a9a219
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/network/structs.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <aidl/android/hardware/radio/network/BarringInfo.h>
+#include <aidl/android/hardware/radio/network/CellIdentity.h>
+#include <aidl/android/hardware/radio/network/CellInfo.h>
+#include <aidl/android/hardware/radio/network/LceDataInfo.h>
+#include <aidl/android/hardware/radio/network/LinkCapacityEstimate.h>
+#include <aidl/android/hardware/radio/network/NetworkScanRequest.h>
+#include <aidl/android/hardware/radio/network/NetworkScanResult.h>
+#include <aidl/android/hardware/radio/network/OperatorInfo.h>
+#include <aidl/android/hardware/radio/network/PhysicalChannelConfig.h>
+#include <aidl/android/hardware/radio/network/RadioAccessSpecifier.h>
+#include <aidl/android/hardware/radio/network/RadioBandMode.h>
+#include <aidl/android/hardware/radio/network/RegStateResult.h>
+#include <aidl/android/hardware/radio/network/SignalStrength.h>
+#include <aidl/android/hardware/radio/network/SignalThresholdInfo.h>
+#include <aidl/android/hardware/radio/network/SuppSvcNotification.h>
+#include <android/hardware/radio/1.6/types.h>
+
+namespace android::hardware::radio::compat {
+
+::aidl::android::hardware::radio::network::RadioBandMode toAidl(V1_0::RadioBandMode mode);
+::aidl::android::hardware::radio::network::GeranBands toAidl(V1_1::GeranBands band);
+V1_1::GeranBands toHidl(::aidl::android::hardware::radio::network::GeranBands band);
+::aidl::android::hardware::radio::network::UtranBands toAidl(V1_5::UtranBands band);
+V1_5::UtranBands toHidl(::aidl::android::hardware::radio::network::UtranBands band);
+::aidl::android::hardware::radio::network::EutranBands toAidl(V1_5::EutranBands band);
+V1_5::EutranBands toHidl(::aidl::android::hardware::radio::network::EutranBands band);
+::aidl::android::hardware::radio::network::NgranBands toAidl(V1_5::NgranBands band);
+V1_5::NgranBands toHidl(::aidl::android::hardware::radio::network::NgranBands band);
+
+V1_5::SignalThresholdInfo  //
+toHidl(const ::aidl::android::hardware::radio::network::SignalThresholdInfo& info);
+
+::aidl::android::hardware::radio::network::RadioAccessSpecifier  //
+toAidl(const V1_5::RadioAccessSpecifier& spec);
+V1_5::RadioAccessNetworks  //
+toRadioAccessNetworks(::aidl::android::hardware::radio::AccessNetwork val);
+V1_5::RadioAccessSpecifier  //
+toHidl(const ::aidl::android::hardware::radio::network::RadioAccessSpecifier& spec);
+
+V1_5::NetworkScanRequest  //
+toHidl(const ::aidl::android::hardware::radio::network::NetworkScanRequest& req);
+
+::aidl::android::hardware::radio::network::CellIdentity toAidl(const V1_5::CellIdentity& ci);
+
+::aidl::android::hardware::radio::network::BarringInfo toAidl(const V1_5::BarringInfo& info);
+
+::aidl::android::hardware::radio::network::ClosedSubscriberGroupInfo  //
+toAidl(const V1_5::ClosedSubscriberGroupInfo& info);
+
+::aidl::android::hardware::radio::network::CellInfo toAidl(const V1_5::CellInfo& info);
+::aidl::android::hardware::radio::network::CellInfo toAidl(const V1_6::CellInfo& info);
+
+::aidl::android::hardware::radio::network::LinkCapacityEstimate  //
+toAidl(const V1_2::LinkCapacityEstimate& lce);
+::aidl::android::hardware::radio::network::LinkCapacityEstimate  //
+toAidl(const V1_6::LinkCapacityEstimate& lce);
+
+::aidl::android::hardware::radio::network::PhysicalChannelConfig  //
+toAidl(const V1_4::PhysicalChannelConfig& cfg);
+::aidl::android::hardware::radio::network::PhysicalChannelConfig  //
+toAidl(const V1_6::PhysicalChannelConfig& cfg);
+
+::aidl::android::hardware::radio::network::SignalStrength toAidl(const V1_4::SignalStrength& sig);
+::aidl::android::hardware::radio::network::SignalStrength toAidl(const V1_6::SignalStrength& sig);
+
+::aidl::android::hardware::radio::network::NetworkScanResult  //
+toAidl(const V1_5::NetworkScanResult& res);
+::aidl::android::hardware::radio::network::NetworkScanResult  //
+toAidl(const V1_6::NetworkScanResult& res);
+
+::aidl::android::hardware::radio::network::SuppSvcNotification  //
+toAidl(const V1_0::SuppSvcNotification& svc);
+
+::aidl::android::hardware::radio::network::OperatorInfo toAidl(const V1_0::OperatorInfo& info);
+
+::aidl::android::hardware::radio::network::RegStateResult toAidl(const V1_5::RegStateResult& res);
+::aidl::android::hardware::radio::network::RegStateResult toAidl(const V1_6::RegStateResult& res);
+
+::aidl::android::hardware::radio::network::LceDataInfo toAidl(const V1_0::LceDataInfo& info);
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/network/utils.cpp b/radio/aidl/compat/libradiocompat/network/utils.cpp
new file mode 100644
index 0000000..6fe3e6e
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/network/utils.cpp
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "utils.h"
+
+namespace android::hardware::radio::compat {
+
+namespace RAF {
+using E = V1_4::RadioAccessFamily;
+constexpr auto GSM = E::GSM | E::GPRS;
+constexpr auto CDMA = E::IS95A | E::IS95B | E::ONE_X_RTT;
+constexpr auto EVDO = E::EVDO_0 | E::EVDO_A | E::EVDO_B | E::EHRPD;
+constexpr auto HS = E::HSUPA | E::HSDPA | E::HSPA | E::HSPAP;
+constexpr auto WCDMA = HS | E::UMTS;
+constexpr auto LTE = E::LTE | E::LTE_CA;
+constexpr auto NR = E::NR;
+}  // namespace RAF
+
+static hidl_bitfield<V1_4::RadioAccessFamily>  //
+getAdjustedRaf(hidl_bitfield<V1_4::RadioAccessFamily> raf) {
+    if (raf & RAF::GSM) raf |= RAF::GSM;
+    if (raf & RAF::WCDMA) raf |= RAF::WCDMA;
+    if (raf & RAF::CDMA) raf |= RAF::CDMA;
+    if (raf & RAF::EVDO) raf |= RAF::EVDO;
+    if (raf & RAF::LTE) raf |= RAF::LTE;
+    if (raf & RAF::NR) raf |= RAF::NR;
+
+    return raf;
+}
+
+V1_0::PreferredNetworkType getNetworkTypeFromRaf(hidl_bitfield<V1_4::RadioAccessFamily> raf) {
+    raf = getAdjustedRaf(raf);
+    switch (raf) {
+        case RAF::GSM | RAF::WCDMA:
+            return V1_0::PreferredNetworkType::GSM_WCDMA_AUTO;
+        case RAF::GSM:
+            return V1_0::PreferredNetworkType::GSM_ONLY;
+        case RAF::WCDMA:
+            return V1_0::PreferredNetworkType::WCDMA;
+        case (RAF::CDMA | RAF::EVDO):
+            return V1_0::PreferredNetworkType::CDMA_EVDO_AUTO;
+        case (RAF::LTE | RAF::CDMA | RAF::EVDO):
+            return V1_0::PreferredNetworkType::LTE_CDMA_EVDO;
+        case (RAF::LTE | RAF::GSM | RAF::WCDMA):
+            return V1_0::PreferredNetworkType::LTE_GSM_WCDMA;
+        case (RAF::LTE | RAF::CDMA | RAF::EVDO | RAF::GSM | RAF::WCDMA):
+            return V1_0::PreferredNetworkType::LTE_CMDA_EVDO_GSM_WCDMA;  // CDMA typo
+        case RAF::LTE:
+            return V1_0::PreferredNetworkType::LTE_ONLY;
+        case (RAF::LTE | RAF::WCDMA):
+            return V1_0::PreferredNetworkType::LTE_WCDMA;
+        case RAF::CDMA:
+            return V1_0::PreferredNetworkType::CDMA_ONLY;
+        case RAF::EVDO:
+            return V1_0::PreferredNetworkType::EVDO_ONLY;
+        case (RAF::GSM | RAF::WCDMA | RAF::CDMA | RAF::EVDO):
+            return V1_0::PreferredNetworkType::GSM_WCDMA_CDMA_EVDO_AUTO;
+        case static_cast<int>(RAF::E::TD_SCDMA):
+            return V1_0::PreferredNetworkType::TD_SCDMA_ONLY;
+        case (RAF::E::TD_SCDMA | RAF::WCDMA):
+            return V1_0::PreferredNetworkType::TD_SCDMA_WCDMA;
+        case (RAF::LTE | RAF::E::TD_SCDMA):
+            return V1_0::PreferredNetworkType::TD_SCDMA_LTE;
+        case (RAF::E::TD_SCDMA | RAF::GSM):
+            return V1_0::PreferredNetworkType::TD_SCDMA_GSM;
+        case (RAF::LTE | RAF::E::TD_SCDMA | RAF::GSM):
+            return V1_0::PreferredNetworkType::TD_SCDMA_GSM_LTE;
+        case (RAF::E::TD_SCDMA | RAF::GSM | RAF::WCDMA):
+            return V1_0::PreferredNetworkType::TD_SCDMA_GSM_WCDMA;
+        case (RAF::LTE | RAF::E::TD_SCDMA | RAF::WCDMA):
+            return V1_0::PreferredNetworkType::TD_SCDMA_WCDMA_LTE;
+        case (RAF::LTE | RAF::E::TD_SCDMA | RAF::GSM | RAF::WCDMA):
+            return V1_0::PreferredNetworkType::TD_SCDMA_GSM_WCDMA_LTE;
+        case (RAF::E::TD_SCDMA | RAF::CDMA | RAF::EVDO | RAF::GSM | RAF::WCDMA):
+            return V1_0::PreferredNetworkType::TD_SCDMA_GSM_WCDMA_CDMA_EVDO_AUTO;
+        case (RAF::LTE | RAF::E::TD_SCDMA | RAF::CDMA | RAF::EVDO | RAF::GSM | RAF::WCDMA):
+            return V1_0::PreferredNetworkType::TD_SCDMA_LTE_CDMA_EVDO_GSM_WCDMA;
+        case static_cast<int>(RAF::NR):
+            return V1_0::PreferredNetworkType(23);  //  NR_ONLY
+        case (RAF::NR | RAF::LTE):
+            return V1_0::PreferredNetworkType(24);  //  NR_LTE
+        case (RAF::NR | RAF::LTE | RAF::CDMA | RAF::EVDO):
+            return V1_0::PreferredNetworkType(25);  //  NR_LTE_CDMA_EVDO
+        case (RAF::NR | RAF::LTE | RAF::GSM | RAF::WCDMA):
+            return V1_0::PreferredNetworkType(26);  //  NR_LTE_GSM_WCDMA
+        case (RAF::NR | RAF::LTE | RAF::CDMA | RAF::EVDO | RAF::GSM | RAF::WCDMA):
+            return V1_0::PreferredNetworkType(27);  //  NR_LTE_CDMA_EVDO_GSM_WCDMA
+        case (RAF::NR | RAF::LTE | RAF::WCDMA):
+            return V1_0::PreferredNetworkType(28);  //  NR_LTE_WCDMA
+        case (RAF::NR | RAF::LTE | RAF::E::TD_SCDMA):
+            return V1_0::PreferredNetworkType(29);  //  NR_LTE_TDSCDMA
+        case (RAF::NR | RAF::LTE | RAF::E::TD_SCDMA | RAF::GSM):
+            return V1_0::PreferredNetworkType(30);  //  NR_LTE_TDSCDMA_GSM
+        case (RAF::NR | RAF::LTE | RAF::E::TD_SCDMA | RAF::WCDMA):
+            return V1_0::PreferredNetworkType(31);  //  NR_LTE_TDSCDMA_WCDMA
+        case (RAF::NR | RAF::LTE | RAF::E::TD_SCDMA | RAF::GSM | RAF::WCDMA):
+            return V1_0::PreferredNetworkType(32);  //  NR_LTE_TDSCDMA_GSM_WCDMA
+        case (RAF::NR | RAF::LTE | RAF::E::TD_SCDMA | RAF::CDMA | RAF::EVDO | RAF::GSM |
+              RAF::WCDMA):
+            return V1_0::PreferredNetworkType(33);  //  NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA
+        default:
+            return V1_0::PreferredNetworkType::WCDMA;
+    }
+}
+
+hidl_bitfield<V1_4::RadioAccessFamily> getRafFromNetworkType(V1_0::PreferredNetworkType type) {
+    switch (type) {
+        case V1_0::PreferredNetworkType::GSM_WCDMA_AUTO:
+            return RAF::GSM | RAF::WCDMA;
+        case V1_0::PreferredNetworkType::GSM_ONLY:
+            return RAF::GSM;
+        case V1_0::PreferredNetworkType::WCDMA:
+            return RAF::WCDMA;
+        case V1_0::PreferredNetworkType::CDMA_EVDO_AUTO:
+            return (RAF::CDMA | RAF::EVDO);
+        case V1_0::PreferredNetworkType::LTE_CDMA_EVDO:
+            return (RAF::LTE | RAF::CDMA | RAF::EVDO);
+        case V1_0::PreferredNetworkType::LTE_GSM_WCDMA:
+            return (RAF::LTE | RAF::GSM | RAF::WCDMA);
+        case V1_0::PreferredNetworkType::LTE_CMDA_EVDO_GSM_WCDMA:
+            return (RAF::LTE | RAF::CDMA | RAF::EVDO | RAF::GSM | RAF::WCDMA);
+        case V1_0::PreferredNetworkType::LTE_ONLY:
+            return RAF::LTE;
+        case V1_0::PreferredNetworkType::LTE_WCDMA:
+            return (RAF::LTE | RAF::WCDMA);
+        case V1_0::PreferredNetworkType::CDMA_ONLY:
+            return RAF::CDMA;
+        case V1_0::PreferredNetworkType::EVDO_ONLY:
+            return RAF::EVDO;
+        case V1_0::PreferredNetworkType::GSM_WCDMA_CDMA_EVDO_AUTO:
+            return (RAF::GSM | RAF::WCDMA | RAF::CDMA | RAF::EVDO);
+        case V1_0::PreferredNetworkType::TD_SCDMA_ONLY:
+            return static_cast<int>(RAF::E::TD_SCDMA);
+        case V1_0::PreferredNetworkType::TD_SCDMA_WCDMA:
+            return (RAF::E::TD_SCDMA | RAF::WCDMA);
+        case V1_0::PreferredNetworkType::TD_SCDMA_LTE:
+            return (RAF::LTE | RAF::E::TD_SCDMA);
+        case V1_0::PreferredNetworkType::TD_SCDMA_GSM:
+            return (RAF::E::TD_SCDMA | RAF::GSM);
+        case V1_0::PreferredNetworkType::TD_SCDMA_GSM_LTE:
+            return (RAF::LTE | RAF::E::TD_SCDMA | RAF::GSM);
+        case V1_0::PreferredNetworkType::TD_SCDMA_GSM_WCDMA:
+            return (RAF::E::TD_SCDMA | RAF::GSM | RAF::WCDMA);
+        case V1_0::PreferredNetworkType::TD_SCDMA_WCDMA_LTE:
+            return (RAF::LTE | RAF::E::TD_SCDMA | RAF::WCDMA);
+        case V1_0::PreferredNetworkType::TD_SCDMA_GSM_WCDMA_LTE:
+            return (RAF::LTE | RAF::E::TD_SCDMA | RAF::GSM | RAF::WCDMA);
+        case V1_0::PreferredNetworkType::TD_SCDMA_GSM_WCDMA_CDMA_EVDO_AUTO:
+            return (RAF::E::TD_SCDMA | RAF::CDMA | RAF::EVDO | RAF::GSM | RAF::WCDMA);
+        case V1_0::PreferredNetworkType::TD_SCDMA_LTE_CDMA_EVDO_GSM_WCDMA:
+            return (RAF::LTE | RAF::E::TD_SCDMA | RAF::CDMA | RAF::EVDO | RAF::GSM | RAF::WCDMA);
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wswitch"
+        case V1_0::PreferredNetworkType(23):  //  NR_ONLY
+            return static_cast<int>(RAF::NR);
+        case V1_0::PreferredNetworkType(24):  //  NR_LTE
+            return (RAF::NR | RAF::LTE);
+        case V1_0::PreferredNetworkType(25):  //  NR_LTE_CDMA_EVDO
+            return (RAF::NR | RAF::LTE | RAF::CDMA | RAF::EVDO);
+        case V1_0::PreferredNetworkType(26):  //  NR_LTE_GSM_WCDMA
+            return (RAF::NR | RAF::LTE | RAF::GSM | RAF::WCDMA);
+        case V1_0::PreferredNetworkType(27):  //  NR_LTE_CDMA_EVDO_GSM_WCDMA
+            return (RAF::NR | RAF::LTE | RAF::CDMA | RAF::EVDO | RAF::GSM | RAF::WCDMA);
+        case V1_0::PreferredNetworkType(28):  //  NR_LTE_WCDMA
+            return (RAF::NR | RAF::LTE | RAF::WCDMA);
+        case V1_0::PreferredNetworkType(29):  //  NR_LTE_TDSCDMA
+            return (RAF::NR | RAF::LTE | RAF::E::TD_SCDMA);
+        case V1_0::PreferredNetworkType(30):  //  NR_LTE_TDSCDMA_GSM
+            return (RAF::NR | RAF::LTE | RAF::E::TD_SCDMA | RAF::GSM);
+        case V1_0::PreferredNetworkType(31):  //  NR_LTE_TDSCDMA_WCDMA
+            return (RAF::NR | RAF::LTE | RAF::E::TD_SCDMA | RAF::WCDMA);
+        case V1_0::PreferredNetworkType(32):  //  NR_LTE_TDSCDMA_GSM_WCDMA
+            return (RAF::NR | RAF::LTE | RAF::E::TD_SCDMA | RAF::GSM | RAF::WCDMA);
+        case V1_0::PreferredNetworkType(33):  //  NR_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA
+            return (RAF::NR | RAF::LTE | RAF::E::TD_SCDMA | RAF::CDMA | RAF::EVDO | RAF::GSM |
+                    RAF::WCDMA);
+#pragma GCC diagnostic pop
+        default:
+            return {};  // unknown
+    }
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/network/utils.h b/radio/aidl/compat/libradiocompat/network/utils.h
new file mode 100644
index 0000000..10714be
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/network/utils.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <android/hardware/radio/1.4/types.h>
+
+namespace android::hardware::radio::compat {
+
+V1_0::PreferredNetworkType getNetworkTypeFromRaf(hidl_bitfield<V1_4::RadioAccessFamily> raf);
+hidl_bitfield<V1_4::RadioAccessFamily> getRafFromNetworkType(V1_0::PreferredNetworkType type);
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/sim/RadioIndication-sim.cpp b/radio/aidl/compat/libradiocompat/sim/RadioIndication-sim.cpp
new file mode 100644
index 0000000..3938e00
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/sim/RadioIndication-sim.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libradiocompat/RadioIndication.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "SimIndication"
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::sim;
+
+void RadioIndication::setResponseFunction(std::shared_ptr<aidl::IRadioSimIndication> simCb) {
+    mSimCb = simCb;
+}
+
+std::shared_ptr<aidl::IRadioSimIndication> RadioIndication::simCb() {
+    return mSimCb.get();
+}
+
+Return<void> RadioIndication::carrierInfoForImsiEncryption(V1_0::RadioIndicationType type) {
+    LOG_CALL << type;
+    simCb()->carrierInfoForImsiEncryption(toAidl(type));
+    return {};
+}
+
+Return<void> RadioIndication::cdmaSubscriptionSourceChanged(
+        V1_0::RadioIndicationType type, V1_0::CdmaSubscriptionSource cdmaSource) {
+    LOG_CALL << type;
+    simCb()->cdmaSubscriptionSourceChanged(toAidl(type), aidl::CdmaSubscriptionSource(cdmaSource));
+    return {};
+}
+
+Return<void> RadioIndication::simPhonebookChanged(V1_0::RadioIndicationType type) {
+    LOG_CALL << type;
+    simCb()->simPhonebookChanged(toAidl(type));
+    return {};
+}
+
+Return<void> RadioIndication::simPhonebookRecordsReceived(
+        V1_0::RadioIndicationType type, V1_6::PbReceivedStatus status,
+        const hidl_vec<V1_6::PhonebookRecordInfo>& rec) {
+    LOG_CALL << type;
+    simCb()->simPhonebookRecordsReceived(toAidl(type), aidl::PbReceivedStatus(status), toAidl(rec));
+    return {};
+}
+
+Return<void> RadioIndication::simRefresh(V1_0::RadioIndicationType type,
+                                         const V1_0::SimRefreshResult& refreshResult) {
+    LOG_CALL << type;
+    simCb()->simRefresh(toAidl(type), toAidl(refreshResult));
+    return {};
+}
+
+Return<void> RadioIndication::simStatusChanged(V1_0::RadioIndicationType type) {
+    LOG_CALL << type;
+    simCb()->simStatusChanged(toAidl(type));
+    return {};
+}
+
+Return<void> RadioIndication::stkEventNotify(V1_0::RadioIndicationType type,
+                                             const hidl_string& cmd) {
+    LOG_CALL << type;
+    simCb()->stkEventNotify(toAidl(type), cmd);
+    return {};
+}
+
+Return<void> RadioIndication::stkProactiveCommand(V1_0::RadioIndicationType type,
+                                                  const hidl_string& cmd) {
+    LOG_CALL << type;
+    simCb()->stkProactiveCommand(toAidl(type), cmd);
+    return {};
+}
+
+Return<void> RadioIndication::stkSessionEnd(V1_0::RadioIndicationType type) {
+    LOG_CALL << type;
+    simCb()->stkSessionEnd(toAidl(type));
+    return {};
+}
+
+Return<void> RadioIndication::subscriptionStatusChanged(V1_0::RadioIndicationType type,
+                                                        bool activate) {
+    LOG_CALL << type;
+    simCb()->subscriptionStatusChanged(toAidl(type), activate);
+    return {};
+}
+
+Return<void> RadioIndication::uiccApplicationsEnablementChanged(V1_0::RadioIndicationType type,
+                                                                bool enabled) {
+    LOG_CALL << type;
+    simCb()->uiccApplicationsEnablementChanged(toAidl(type), enabled);
+    return {};
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/sim/RadioResponse-sim.cpp b/radio/aidl/compat/libradiocompat/sim/RadioResponse-sim.cpp
new file mode 100644
index 0000000..3ad9130
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/sim/RadioResponse-sim.cpp
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libradiocompat/RadioResponse.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "SimResponse"
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::sim;
+
+void RadioResponse::setResponseFunction(std::shared_ptr<aidl::IRadioSimResponse> simCb) {
+    mSimCb = simCb;
+}
+
+std::shared_ptr<aidl::IRadioSimResponse> RadioResponse::simCb() {
+    return mSimCb.get();
+}
+
+Return<void> RadioResponse::areUiccApplicationsEnabledResponse(const V1_0::RadioResponseInfo& info,
+                                                               bool enabled) {
+    LOG_CALL << info.serial;
+    simCb()->areUiccApplicationsEnabledResponse(toAidl(info), enabled);
+    return {};
+}
+
+Return<void> RadioResponse::changeIccPin2ForAppResponse(const V1_0::RadioResponseInfo& info,
+                                                        int32_t remainingRetries) {
+    LOG_CALL << info.serial;
+    simCb()->changeIccPin2ForAppResponse(toAidl(info), remainingRetries);
+    return {};
+}
+
+Return<void> RadioResponse::changeIccPinForAppResponse(const V1_0::RadioResponseInfo& info,
+                                                       int32_t remainingRetries) {
+    LOG_CALL << info.serial;
+    simCb()->changeIccPinForAppResponse(toAidl(info), remainingRetries);
+    return {};
+}
+
+Return<void> RadioResponse::enableUiccApplicationsResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    simCb()->enableUiccApplicationsResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::getAllowedCarriersResponse(  //
+        const V1_0::RadioResponseInfo& info, bool allAllowed, const V1_0::CarrierRestrictions& cr) {
+    LOG_CALL << info.serial;
+    aidl::CarrierRestrictions aidlCr = toAidl(cr);
+    if (allAllowed) aidlCr = {};
+    simCb()->getAllowedCarriersResponse(toAidl(info), aidlCr, {});
+    return {};
+}
+
+Return<void> RadioResponse::getAllowedCarriersResponse_1_4(
+        const V1_0::RadioResponseInfo& info, const V1_4::CarrierRestrictionsWithPriority& carriers,
+        V1_4::SimLockMultiSimPolicy multiSimPolicy) {
+    LOG_CALL << info.serial;
+    simCb()->getAllowedCarriersResponse(toAidl(info), toAidl(carriers),
+                                        aidl::SimLockMultiSimPolicy(multiSimPolicy));
+    return {};
+}
+
+Return<void> RadioResponse::getCDMASubscriptionResponse(
+        const V1_0::RadioResponseInfo& info, const hidl_string& mdn, const hidl_string& hSid,
+        const hidl_string& hNid, const hidl_string& min, const hidl_string& prl) {
+    LOG_CALL << info.serial;
+    simCb()->getCdmaSubscriptionResponse(toAidl(info), mdn, hSid, hNid, min, prl);
+    return {};
+}
+
+Return<void> RadioResponse::getCdmaSubscriptionSourceResponse(const V1_0::RadioResponseInfo& info,
+                                                              V1_0::CdmaSubscriptionSource s) {
+    LOG_CALL << info.serial;
+    simCb()->getCdmaSubscriptionSourceResponse(toAidl(info), aidl::CdmaSubscriptionSource(s));
+    return {};
+}
+
+Return<void> RadioResponse::getFacilityLockForAppResponse(const V1_0::RadioResponseInfo& info,
+                                                          int32_t response) {
+    LOG_CALL << info.serial;
+    simCb()->getFacilityLockForAppResponse(toAidl(info), response);
+    return {};
+}
+
+Return<void> RadioResponse::getIccCardStatusResponse(const V1_0::RadioResponseInfo& info,
+                                                     const V1_0::CardStatus& cardStatus) {
+    LOG_CALL << info.serial;
+    simCb()->getIccCardStatusResponse(toAidl(info), toAidl(cardStatus));
+    return {};
+}
+
+Return<void> RadioResponse::getIccCardStatusResponse_1_2(const V1_0::RadioResponseInfo& info,
+                                                         const V1_2::CardStatus& cardStatus) {
+    LOG_CALL << info.serial;
+    simCb()->getIccCardStatusResponse(toAidl(info), toAidl(cardStatus));
+    return {};
+}
+
+Return<void> RadioResponse::getIccCardStatusResponse_1_4(const V1_0::RadioResponseInfo& info,
+                                                         const V1_4::CardStatus& cardStatus) {
+    LOG_CALL << info.serial;
+    simCb()->getIccCardStatusResponse(toAidl(info), toAidl(cardStatus));
+    return {};
+}
+
+Return<void> RadioResponse::getIccCardStatusResponse_1_5(const V1_0::RadioResponseInfo& info,
+                                                         const V1_5::CardStatus& cardStatus) {
+    LOG_CALL << info.serial;
+    simCb()->getIccCardStatusResponse(toAidl(info), toAidl(cardStatus));
+    return {};
+}
+
+Return<void> RadioResponse::getIMSIForAppResponse(const V1_0::RadioResponseInfo& info,
+                                                  const hidl_string& imsi) {
+    LOG_CALL << info.serial;
+    simCb()->getImsiForAppResponse(toAidl(info), imsi);
+    return {};
+}
+
+Return<void> RadioResponse::getSimPhonebookCapacityResponse(
+        const V1_6::RadioResponseInfo& info, const V1_6::PhonebookCapacity& capacity) {
+    LOG_CALL << info.serial;
+    simCb()->getSimPhonebookCapacityResponse(toAidl(info), toAidl(capacity));
+    return {};
+}
+
+Return<void> RadioResponse::getSimPhonebookRecordsResponse(const V1_6::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    simCb()->getSimPhonebookRecordsResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::iccCloseLogicalChannelResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    simCb()->iccCloseLogicalChannelResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::iccIOForAppResponse(const V1_0::RadioResponseInfo& info,
+                                                const V1_0::IccIoResult& iccIo) {
+    LOG_CALL << info.serial;
+    simCb()->iccIoForAppResponse(toAidl(info), toAidl(iccIo));
+    return {};
+}
+
+Return<void> RadioResponse::iccOpenLogicalChannelResponse(  //
+        const V1_0::RadioResponseInfo& info, int32_t chanId, const hidl_vec<int8_t>& selectResp) {
+    LOG_CALL << info.serial;
+    simCb()->iccOpenLogicalChannelResponse(toAidl(info), chanId, toAidl(selectResp));
+    return {};
+}
+
+Return<void> RadioResponse::iccTransmitApduBasicChannelResponse(const V1_0::RadioResponseInfo& info,
+                                                                const V1_0::IccIoResult& result) {
+    LOG_CALL << info.serial;
+    simCb()->iccTransmitApduBasicChannelResponse(toAidl(info), toAidl(result));
+    return {};
+}
+
+Return<void> RadioResponse::iccTransmitApduLogicalChannelResponse(
+        const V1_0::RadioResponseInfo& info, const V1_0::IccIoResult& result) {
+    LOG_CALL << info.serial;
+    simCb()->iccTransmitApduLogicalChannelResponse(toAidl(info), toAidl(result));
+    return {};
+}
+
+Return<void> RadioResponse::reportStkServiceIsRunningResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    simCb()->reportStkServiceIsRunningResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::requestIccSimAuthenticationResponse(const V1_0::RadioResponseInfo& info,
+                                                                const V1_0::IccIoResult& result) {
+    LOG_CALL << info.serial;
+    simCb()->requestIccSimAuthenticationResponse(toAidl(info), toAidl(result));
+    return {};
+}
+
+Return<void> RadioResponse::requestIsimAuthenticationResponse(const V1_0::RadioResponseInfo& info,
+                                                              const hidl_string&) {
+    LOG_CALL << info.serial;
+    LOG(ERROR) << "requestIsimAuthenticationResponse is not supposed to be called";
+    return {};
+}
+
+Return<void> RadioResponse::sendEnvelopeResponse(const V1_0::RadioResponseInfo& info,
+                                                 const hidl_string& commandResponse) {
+    LOG_CALL << info.serial;
+    simCb()->sendEnvelopeResponse(toAidl(info), commandResponse);
+    return {};
+}
+
+Return<void> RadioResponse::sendEnvelopeWithStatusResponse(const V1_0::RadioResponseInfo& info,
+                                                           const V1_0::IccIoResult& iccIo) {
+    LOG_CALL << info.serial;
+    simCb()->sendEnvelopeWithStatusResponse(toAidl(info), toAidl(iccIo));
+    return {};
+}
+
+Return<void> RadioResponse::sendTerminalResponseToSimResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    simCb()->sendTerminalResponseToSimResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setAllowedCarriersResponse(const V1_0::RadioResponseInfo& info,
+                                                       int32_t numAllowed) {
+    LOG_CALL << info.serial << ' ' << numAllowed;
+    simCb()->setAllowedCarriersResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setAllowedCarriersResponse_1_4(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    simCb()->setAllowedCarriersResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setCarrierInfoForImsiEncryptionResponse(
+        const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    simCb()->setCarrierInfoForImsiEncryptionResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setCdmaSubscriptionSourceResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    simCb()->setCdmaSubscriptionSourceResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setFacilityLockForAppResponse(const V1_0::RadioResponseInfo& info,
+                                                          int32_t retry) {
+    LOG_CALL << info.serial;
+    simCb()->setFacilityLockForAppResponse(toAidl(info), retry);
+    return {};
+}
+
+Return<void> RadioResponse::setSimCardPowerResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    simCb()->setSimCardPowerResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setSimCardPowerResponse_1_1(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    simCb()->setSimCardPowerResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setSimCardPowerResponse_1_6(const V1_6::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    simCb()->setSimCardPowerResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setUiccSubscriptionResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    simCb()->setUiccSubscriptionResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::supplyIccPin2ForAppResponse(const V1_0::RadioResponseInfo& info,
+                                                        int32_t remainingRetries) {
+    LOG_CALL << info.serial;
+    simCb()->supplyIccPin2ForAppResponse(toAidl(info), remainingRetries);
+    return {};
+}
+
+Return<void> RadioResponse::supplyIccPinForAppResponse(const V1_0::RadioResponseInfo& info,
+                                                       int32_t remainingRetries) {
+    LOG_CALL << info.serial;
+    simCb()->supplyIccPinForAppResponse(toAidl(info), remainingRetries);
+    return {};
+}
+
+Return<void> RadioResponse::supplyIccPuk2ForAppResponse(const V1_0::RadioResponseInfo& info,
+                                                        int32_t remainingRetries) {
+    LOG_CALL << info.serial;
+    simCb()->supplyIccPuk2ForAppResponse(toAidl(info), remainingRetries);
+    return {};
+}
+
+Return<void> RadioResponse::supplyIccPukForAppResponse(const V1_0::RadioResponseInfo& info,
+                                                       int32_t remainingRetries) {
+    LOG_CALL << info.serial;
+    simCb()->supplyIccPukForAppResponse(toAidl(info), remainingRetries);
+    return {};
+}
+
+Return<void> RadioResponse::supplySimDepersonalizationResponse(const V1_0::RadioResponseInfo& info,
+                                                               V1_5::PersoSubstate persoType,
+                                                               int32_t rRet) {
+    LOG_CALL << info.serial;
+    simCb()->supplySimDepersonalizationResponse(toAidl(info), aidl::PersoSubstate(persoType), rRet);
+    return {};
+}
+
+Return<void> RadioResponse::updateSimPhonebookRecordsResponse(const V1_6::RadioResponseInfo& info,
+                                                              int32_t updatedRecordIndex) {
+    LOG_CALL << info.serial;
+    simCb()->updateSimPhonebookRecordsResponse(toAidl(info), updatedRecordIndex);
+    return {};
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/sim/RadioSim.cpp b/radio/aidl/compat/libradiocompat/sim/RadioSim.cpp
new file mode 100644
index 0000000..b43f64f
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/sim/RadioSim.cpp
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libradiocompat/RadioSim.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "Sim"
+
+namespace android::hardware::radio::compat {
+
+using ::ndk::ScopedAStatus;
+namespace aidl = ::aidl::android::hardware::radio::sim;
+constexpr auto ok = &ScopedAStatus::ok;
+
+std::shared_ptr<aidl::IRadioSimResponse> RadioSim::respond() {
+    return mCallbackManager->response().simCb();
+}
+
+ScopedAStatus RadioSim::areUiccApplicationsEnabled(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->areUiccApplicationsEnabled(serial);
+    return ok();
+}
+
+ScopedAStatus RadioSim::changeIccPin2ForApp(int32_t serial, const std::string& oldPin2,
+                                            const std::string& newPin2, const std::string& aid) {
+    LOG_CALL << serial;
+    mHal1_5->changeIccPin2ForApp(serial, oldPin2, newPin2, aid);
+    return ok();
+}
+
+ScopedAStatus RadioSim::changeIccPinForApp(int32_t serial, const std::string& oldPin,
+                                           const std::string& newPin, const std::string& aid) {
+    LOG_CALL << serial;
+    mHal1_5->changeIccPinForApp(serial, oldPin, newPin, aid);
+    return ok();
+}
+
+ScopedAStatus RadioSim::enableUiccApplications(int32_t serial, bool enable) {
+    LOG_CALL << serial;
+    mHal1_5->enableUiccApplications(serial, enable);
+    return ok();
+}
+
+ScopedAStatus RadioSim::getAllowedCarriers(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getAllowedCarriers_1_4(serial);
+    return ok();
+}
+
+ScopedAStatus RadioSim::getCdmaSubscription(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getCDMASubscription(serial);
+    return ok();
+}
+
+ScopedAStatus RadioSim::getCdmaSubscriptionSource(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getCdmaSubscriptionSource(serial);
+    return ok();
+}
+
+ScopedAStatus RadioSim::getFacilityLockForApp(  //
+        int32_t serial, const std::string& facility, const std::string& password,
+        int32_t serviceClass, const std::string& appId) {
+    LOG_CALL << serial;
+    mHal1_5->getFacilityLockForApp(serial, facility, password, serviceClass, appId);
+    return ok();
+}
+
+ScopedAStatus RadioSim::getIccCardStatus(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getIccCardStatus(serial);
+    return ok();
+}
+
+ScopedAStatus RadioSim::getImsiForApp(int32_t serial, const std::string& aid) {
+    LOG_CALL << serial;
+    mHal1_5->getImsiForApp(serial, aid);
+    return ok();
+}
+
+ScopedAStatus RadioSim::getSimPhonebookCapacity(int32_t serial) {
+    LOG_CALL << serial;
+    if (mHal1_6) {
+        mHal1_6->getSimPhonebookCapacity(serial);
+    } else {
+        respond()->getSimPhonebookCapacityResponse(notSupported(serial), {});
+    }
+    return ok();
+}
+
+ScopedAStatus RadioSim::getSimPhonebookRecords(int32_t serial) {
+    LOG_CALL << serial;
+    if (mHal1_6) {
+        mHal1_6->getSimPhonebookRecords(serial);
+    } else {
+        respond()->getSimPhonebookRecordsResponse(notSupported(serial));
+    }
+    return ok();
+}
+
+ScopedAStatus RadioSim::iccCloseLogicalChannel(int32_t serial, int32_t channelId) {
+    LOG_CALL << serial;
+    mHal1_5->iccCloseLogicalChannel(serial, channelId);
+    return ok();
+}
+
+ScopedAStatus RadioSim::iccIoForApp(int32_t serial, const aidl::IccIo& iccIo) {
+    LOG_CALL << serial;
+    mHal1_5->iccIOForApp(serial, toHidl(iccIo));
+    return ok();
+}
+
+ScopedAStatus RadioSim::iccOpenLogicalChannel(int32_t serial, const std::string& aid, int32_t p2) {
+    LOG_CALL << serial;
+    mHal1_5->iccOpenLogicalChannel(serial, aid, p2);
+    return ok();
+}
+
+ScopedAStatus RadioSim::iccTransmitApduBasicChannel(int32_t serial, const aidl::SimApdu& message) {
+    LOG_CALL << serial;
+    mHal1_5->iccTransmitApduBasicChannel(serial, toHidl(message));
+    return ok();
+}
+
+ScopedAStatus RadioSim::iccTransmitApduLogicalChannel(int32_t serial,
+                                                      const aidl::SimApdu& message) {
+    LOG_CALL << serial;
+    mHal1_5->iccTransmitApduLogicalChannel(serial, toHidl(message));
+    return ok();
+}
+
+ScopedAStatus RadioSim::reportStkServiceIsRunning(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->reportStkServiceIsRunning(serial);
+    return ok();
+}
+
+ScopedAStatus RadioSim::requestIccSimAuthentication(  //
+        int32_t serial, int32_t authContext, const std::string& authData, const std::string& aid) {
+    LOG_CALL << serial;
+    mHal1_5->requestIccSimAuthentication(serial, authContext, authData, aid);
+    return ok();
+}
+
+ScopedAStatus RadioSim::responseAcknowledgement() {
+    LOG_CALL;
+    mHal1_5->responseAcknowledgement();
+    return ok();
+}
+
+ScopedAStatus RadioSim::sendEnvelope(int32_t serial, const std::string& command) {
+    LOG_CALL << serial;
+    mHal1_5->sendEnvelope(serial, command);
+    return ok();
+}
+
+ScopedAStatus RadioSim::sendEnvelopeWithStatus(int32_t serial, const std::string& contents) {
+    LOG_CALL << serial;
+    mHal1_5->sendEnvelopeWithStatus(serial, contents);
+    return ok();
+}
+
+ScopedAStatus RadioSim::sendTerminalResponseToSim(int32_t serial,
+                                                  const std::string& commandResponse) {
+    LOG_CALL << serial;
+    mHal1_5->sendTerminalResponseToSim(serial, commandResponse);
+    return ok();
+}
+
+ScopedAStatus RadioSim::setAllowedCarriers(  //
+        int32_t serial, const aidl::CarrierRestrictions& carriers, aidl::SimLockMultiSimPolicy mp) {
+    LOG_CALL << serial;
+    mHal1_5->setAllowedCarriers_1_4(serial, toHidl(carriers), V1_4::SimLockMultiSimPolicy(mp));
+    return ok();
+}
+
+ScopedAStatus RadioSim::setCarrierInfoForImsiEncryption(
+        int32_t serial, const aidl::ImsiEncryptionInfo& imsiEncryptionInfo) {
+    LOG_CALL << serial;
+    if (mHal1_6) {
+        mHal1_6->setCarrierInfoForImsiEncryption_1_6(serial, toHidl_1_6(imsiEncryptionInfo));
+    } else {
+        mHal1_5->setCarrierInfoForImsiEncryption(serial, toHidl(imsiEncryptionInfo));
+    }
+    return ok();
+}
+
+ScopedAStatus RadioSim::setCdmaSubscriptionSource(int32_t serial,
+                                                  aidl::CdmaSubscriptionSource cdmaSub) {
+    LOG_CALL << serial;
+    mHal1_5->setCdmaSubscriptionSource(serial, V1_0::CdmaSubscriptionSource(cdmaSub));
+    return ok();
+}
+
+ScopedAStatus RadioSim::setFacilityLockForApp(  //
+        int32_t serial, const std::string& facility, bool lockState, const std::string& password,
+        int32_t serviceClass, const std::string& appId) {
+    LOG_CALL << serial;
+    mHal1_5->setFacilityLockForApp(serial, facility, lockState, password, serviceClass, appId);
+    return ok();
+}
+
+ScopedAStatus RadioSim::setResponseFunctions(
+        const std::shared_ptr<aidl::IRadioSimResponse>& response,
+        const std::shared_ptr<aidl::IRadioSimIndication>& indication) {
+    LOG_CALL << response << ' ' << indication;
+    mCallbackManager->setResponseFunctions(response, indication);
+    return ok();
+}
+
+ScopedAStatus RadioSim::setSimCardPower(int32_t serial, aidl::CardPowerState powerUp) {
+    LOG_CALL << serial;
+    if (mHal1_6) {
+        mHal1_6->setSimCardPower_1_6(serial, V1_1::CardPowerState(powerUp));
+    } else {
+        mHal1_5->setSimCardPower_1_1(serial, V1_1::CardPowerState(powerUp));
+    }
+    return ok();
+}
+
+ScopedAStatus RadioSim::setUiccSubscription(int32_t serial, const aidl::SelectUiccSub& uiccSub) {
+    LOG_CALL << serial;
+    mHal1_5->setUiccSubscription(serial, toHidl(uiccSub));
+    return ok();
+}
+
+ScopedAStatus RadioSim::supplyIccPin2ForApp(int32_t serial, const std::string& pin2,
+                                            const std::string& aid) {
+    LOG_CALL << serial;
+    mHal1_5->supplyIccPin2ForApp(serial, pin2, aid);
+    return ok();
+}
+
+ScopedAStatus RadioSim::supplyIccPinForApp(int32_t serial, const std::string& pin,
+                                           const std::string& aid) {
+    LOG_CALL << serial;
+    mHal1_5->supplyIccPinForApp(serial, pin, aid);
+    return ok();
+}
+
+ScopedAStatus RadioSim::supplyIccPuk2ForApp(int32_t serial, const std::string& puk2,
+                                            const std::string& pin2, const std::string& aid) {
+    LOG_CALL << serial;
+    mHal1_5->supplyIccPuk2ForApp(serial, puk2, pin2, aid);
+    return ok();
+}
+
+ScopedAStatus RadioSim::supplyIccPukForApp(int32_t serial, const std::string& puk,
+                                           const std::string& pin, const std::string& aid) {
+    LOG_CALL << serial;
+    mHal1_5->supplyIccPukForApp(serial, puk, pin, aid);
+    return ok();
+}
+
+ScopedAStatus RadioSim::supplySimDepersonalization(int32_t serial, aidl::PersoSubstate pss,
+                                                   const std::string& controlKey) {
+    LOG_CALL << serial;
+    mHal1_5->supplySimDepersonalization(serial, V1_5::PersoSubstate(pss), controlKey);
+    return ok();
+}
+
+ScopedAStatus RadioSim::updateSimPhonebookRecords(int32_t serial,
+                                                  const aidl::PhonebookRecordInfo& recordInfo) {
+    LOG_CALL << serial;
+    if (mHal1_6) {
+        mHal1_6->updateSimPhonebookRecords(serial, toHidl(recordInfo));
+    } else {
+        respond()->updateSimPhonebookRecordsResponse(notSupported(serial), 0);
+    }
+    return ok();
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/sim/structs.cpp b/radio/aidl/compat/libradiocompat/sim/structs.cpp
new file mode 100644
index 0000000..bfbff02
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/sim/structs.cpp
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "structs.h"
+
+#include "commonStructs.h"
+
+#include "collections.h"
+
+#include <android-base/logging.h>
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::sim;
+
+V1_0::IccIo toHidl(const aidl::IccIo& icc) {
+    return {
+            .command = icc.command,
+            .fileId = icc.fileId,
+            .path = icc.path,
+            .p1 = icc.p1,
+            .p2 = icc.p2,
+            .p3 = icc.p3,
+            .data = icc.data,
+            .pin2 = icc.pin2,
+            .aid = icc.aid,
+    };
+}
+
+V1_0::SimApdu toHidl(const aidl::SimApdu& apdu) {
+    return {
+            .sessionId = apdu.sessionId,
+            .cla = apdu.cla,
+            .instruction = apdu.instruction,
+            .p1 = apdu.p1,
+            .p2 = apdu.p2,
+            .p3 = apdu.p3,
+            .data = apdu.data,
+    };
+}
+
+aidl::Carrier toAidl(const V1_0::Carrier& carrier) {
+    return {
+            .mcc = carrier.mcc,
+            .mnc = carrier.mnc,
+            .matchType = static_cast<int32_t>(carrier.matchType),
+            .matchData = carrier.matchData,
+    };
+}
+
+V1_0::Carrier toHidl(const aidl::Carrier& carrier) {
+    return {
+            .mcc = carrier.mcc,
+            .mnc = carrier.mnc,
+            .matchType = V1_0::CarrierMatchType{carrier.matchType},
+            .matchData = carrier.matchData,
+    };
+}
+
+aidl::CarrierRestrictions toAidl(const V1_0::CarrierRestrictions& cr) {
+    return {
+            .allowedCarriers = toAidl(cr.allowedCarriers),
+            .excludedCarriers = toAidl(cr.excludedCarriers),
+            .allowedCarriersPrioritized = true,
+    };
+}
+
+aidl::CarrierRestrictions toAidl(const V1_4::CarrierRestrictionsWithPriority& cr) {
+    return {
+            .allowedCarriers = toAidl(cr.allowedCarriers),
+            .excludedCarriers = toAidl(cr.excludedCarriers),
+            .allowedCarriersPrioritized = cr.allowedCarriersPrioritized,
+    };
+}
+
+V1_4::CarrierRestrictionsWithPriority toHidl(const aidl::CarrierRestrictions& cr) {
+    return {
+            .allowedCarriers = toHidl(cr.allowedCarriers),
+            .excludedCarriers = toHidl(cr.excludedCarriers),
+            .allowedCarriersPrioritized = cr.allowedCarriersPrioritized,
+    };
+}
+
+V1_1::ImsiEncryptionInfo toHidl(const aidl::ImsiEncryptionInfo& info) {
+    return {
+            .mcc = info.mcc,
+            .mnc = info.mnc,
+            .carrierKey = info.carrierKey,
+            .keyIdentifier = info.keyIdentifier,
+            .expirationTime = info.expirationTime,
+    };
+}
+
+V1_6::ImsiEncryptionInfo toHidl_1_6(const aidl::ImsiEncryptionInfo& info) {
+    return {
+            .base = toHidl(info),
+            .keyType = V1_6::PublicKeyType{info.keyType},
+    };
+}
+
+V1_0::SelectUiccSub toHidl(const aidl::SelectUiccSub& sub) {
+    return {
+            .slot = sub.slot,
+            .appIndex = sub.appIndex,
+            .subType = {},
+            .actStatus = {},
+    };
+}
+
+aidl::PhonebookRecordInfo toAidl(const V1_6::PhonebookRecordInfo& info) {
+    return {
+            .recordId = static_cast<int32_t>(info.recordId),
+            .name = info.name,
+            .number = info.number,
+            .emails = toAidl(info.emails),
+            .additionalNumbers = toAidl(info.additionalNumbers),
+    };
+}
+
+V1_6::PhonebookRecordInfo toHidl(const aidl::PhonebookRecordInfo& info) {
+    return {
+            .recordId = static_cast<uint32_t>(info.recordId),
+            .name = info.name,
+            .number = info.number,
+            .emails = toHidl(info.emails),
+            .additionalNumbers = toHidl(info.additionalNumbers),
+    };
+}
+
+aidl::SimRefreshResult toAidl(const V1_0::SimRefreshResult& res) {
+    return {
+            .type = static_cast<int32_t>(res.type),
+            .efId = res.efId,
+            .aid = res.aid,
+    };
+}
+
+aidl::CardStatus toAidl(const V1_0::CardStatus& status) {
+    return toAidl(V1_2::CardStatus{status, 0, "", ""});
+}
+
+aidl::CardStatus toAidl(const V1_2::CardStatus& status) {
+    return toAidl(V1_4::CardStatus{status, ""});
+}
+
+aidl::CardStatus toAidl(const V1_4::CardStatus& status) {
+    auto aidlStatus = toAidl(V1_5::CardStatus{status, {}});
+    aidlStatus.applications = toAidl(status.base.base.applications);
+    return aidlStatus;
+}
+
+aidl::CardStatus toAidl(const V1_5::CardStatus& status) {
+    return {
+            .cardState = static_cast<int32_t>(status.base.base.base.cardState),
+            .universalPinState = aidl::PinState(status.base.base.base.universalPinState),
+            .gsmUmtsSubscriptionAppIndex = status.base.base.base.gsmUmtsSubscriptionAppIndex,
+            .cdmaSubscriptionAppIndex = status.base.base.base.cdmaSubscriptionAppIndex,
+            .imsSubscriptionAppIndex = status.base.base.base.imsSubscriptionAppIndex,
+            .applications = toAidl(status.applications),
+            .atr = status.base.base.atr,
+            .iccid = status.base.base.iccid,
+            .eid = status.base.eid,
+            .slotMap = {static_cast<int32_t>(status.base.base.physicalSlotId), 0},
+    };
+}
+
+aidl::AppStatus toAidl(const V1_0::AppStatus& status) {
+    return toAidl({status, V1_5::PersoSubstate(status.persoSubstate)});
+}
+
+aidl::AppStatus toAidl(const V1_5::AppStatus& status) {
+    return {
+            .appType = static_cast<int32_t>(status.base.appType),
+            .appState = static_cast<int32_t>(status.base.appState),
+            .persoSubstate = aidl::PersoSubstate(status.persoSubstate),
+            .aidPtr = status.base.aidPtr,
+            .appLabelPtr = status.base.appLabelPtr,
+            .pin1Replaced = (status.base.pin1Replaced != 0),
+            .pin1 = aidl::PinState(status.base.pin1),
+            .pin2 = aidl::PinState(status.base.pin2),
+    };
+}
+
+aidl::PhonebookCapacity toAidl(const V1_6::PhonebookCapacity& c) {
+    return {
+            .maxAdnRecords = c.maxAdnRecords,
+            .usedAdnRecords = c.usedAdnRecords,
+            .maxEmailRecords = c.maxEmailRecords,
+            .usedEmailRecords = c.usedEmailRecords,
+            .maxAdditionalNumberRecords = c.maxAdditionalNumberRecords,
+            .usedAdditionalNumberRecords = c.usedAdditionalNumberRecords,
+            .maxNameLen = c.maxNameLen,
+            .maxNumberLen = c.maxNumberLen,
+            .maxEmailLen = c.maxEmailLen,
+            .maxAdditionalNumberLen = c.maxAdditionalNumberLen,
+    };
+}
+
+aidl::IccIoResult toAidl(const V1_0::IccIoResult& iir) {
+    return {
+            .sw1 = iir.sw1,
+            .sw2 = iir.sw2,
+            .simResponse = iir.simResponse,
+    };
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/sim/structs.h b/radio/aidl/compat/libradiocompat/sim/structs.h
new file mode 100644
index 0000000..54099b7
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/sim/structs.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <aidl/android/hardware/radio/sim/AppStatus.h>
+#include <aidl/android/hardware/radio/sim/CardStatus.h>
+#include <aidl/android/hardware/radio/sim/Carrier.h>
+#include <aidl/android/hardware/radio/sim/CarrierRestrictions.h>
+#include <aidl/android/hardware/radio/sim/IccIo.h>
+#include <aidl/android/hardware/radio/sim/IccIoResult.h>
+#include <aidl/android/hardware/radio/sim/ImsiEncryptionInfo.h>
+#include <aidl/android/hardware/radio/sim/PhonebookCapacity.h>
+#include <aidl/android/hardware/radio/sim/PhonebookRecordInfo.h>
+#include <aidl/android/hardware/radio/sim/SelectUiccSub.h>
+#include <aidl/android/hardware/radio/sim/SimApdu.h>
+#include <aidl/android/hardware/radio/sim/SimRefreshResult.h>
+#include <android/hardware/radio/1.6/types.h>
+
+namespace android::hardware::radio::compat {
+
+V1_0::IccIo toHidl(const ::aidl::android::hardware::radio::sim::IccIo& icc);
+
+V1_0::SimApdu toHidl(const ::aidl::android::hardware::radio::sim::SimApdu& apdu);
+
+::aidl::android::hardware::radio::sim::Carrier toAidl(const V1_0::Carrier& carrier);
+V1_0::Carrier toHidl(const ::aidl::android::hardware::radio::sim::Carrier& carrier);
+
+::aidl::android::hardware::radio::sim::CarrierRestrictions  //
+toAidl(const V1_0::CarrierRestrictions& cr);
+::aidl::android::hardware::radio::sim::CarrierRestrictions  //
+toAidl(const V1_4::CarrierRestrictionsWithPriority& cr);
+V1_4::CarrierRestrictionsWithPriority  //
+toHidl(const ::aidl::android::hardware::radio::sim::CarrierRestrictions& cr);
+
+V1_1::ImsiEncryptionInfo  //
+toHidl(const ::aidl::android::hardware::radio::sim::ImsiEncryptionInfo& info);
+V1_6::ImsiEncryptionInfo  //
+toHidl_1_6(const ::aidl::android::hardware::radio::sim::ImsiEncryptionInfo& info);
+
+V1_0::SelectUiccSub toHidl(const ::aidl::android::hardware::radio::sim::SelectUiccSub& sub);
+
+::aidl::android::hardware::radio::sim::PhonebookRecordInfo  //
+toAidl(const V1_6::PhonebookRecordInfo& info);
+V1_6::PhonebookRecordInfo  //
+toHidl(const ::aidl::android::hardware::radio::sim::PhonebookRecordInfo& info);
+
+::aidl::android::hardware::radio::sim::SimRefreshResult  //
+toAidl(const V1_0::SimRefreshResult& res);
+
+::aidl::android::hardware::radio::sim::CardStatus toAidl(const V1_0::CardStatus& status);
+::aidl::android::hardware::radio::sim::CardStatus toAidl(const V1_2::CardStatus& status);
+::aidl::android::hardware::radio::sim::CardStatus toAidl(const V1_4::CardStatus& status);
+::aidl::android::hardware::radio::sim::CardStatus toAidl(const V1_5::CardStatus& status);
+
+::aidl::android::hardware::radio::sim::AppStatus toAidl(const V1_0::AppStatus& status);
+::aidl::android::hardware::radio::sim::AppStatus toAidl(const V1_5::AppStatus& status);
+
+::aidl::android::hardware::radio::sim::PhonebookCapacity toAidl(const V1_6::PhonebookCapacity& c);
+
+::aidl::android::hardware::radio::sim::IccIoResult toAidl(const V1_0::IccIoResult& iir);
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/voice/RadioIndication-voice.cpp b/radio/aidl/compat/libradiocompat/voice/RadioIndication-voice.cpp
new file mode 100644
index 0000000..23878ed
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/voice/RadioIndication-voice.cpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libradiocompat/RadioIndication.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "VoiceIndication"
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::voice;
+
+void RadioIndication::setResponseFunction(std::shared_ptr<aidl::IRadioVoiceIndication> voiceCb) {
+    mVoiceCb = voiceCb;
+}
+
+std::shared_ptr<aidl::IRadioVoiceIndication> RadioIndication::voiceCb() {
+    return mVoiceCb.get();
+}
+
+Return<void> RadioIndication::callRing(V1_0::RadioIndicationType type, bool isGsm,
+                                       const V1_0::CdmaSignalInfoRecord& record) {
+    LOG_CALL << type;
+    voiceCb()->callRing(toAidl(type), isGsm, toAidl(record));
+    return {};
+}
+
+Return<void> RadioIndication::callStateChanged(V1_0::RadioIndicationType type) {
+    LOG_CALL << type;
+    voiceCb()->callStateChanged(toAidl(type));
+    return {};
+}
+
+Return<void> RadioIndication::cdmaCallWaiting(V1_0::RadioIndicationType type,
+                                              const V1_0::CdmaCallWaiting& callWaitingRecord) {
+    LOG_CALL << type;
+    voiceCb()->cdmaCallWaiting(toAidl(type), toAidl(callWaitingRecord));
+    return {};
+}
+
+Return<void> RadioIndication::cdmaInfoRec(V1_0::RadioIndicationType type,
+                                          const V1_0::CdmaInformationRecords& records) {
+    LOG_CALL << type;
+    voiceCb()->cdmaInfoRec(toAidl(type), toAidl(records.infoRec));
+    return {};
+}
+
+Return<void> RadioIndication::cdmaOtaProvisionStatus(V1_0::RadioIndicationType type,
+                                                     V1_0::CdmaOtaProvisionStatus status) {
+    LOG_CALL << type;
+    voiceCb()->cdmaOtaProvisionStatus(toAidl(type), aidl::CdmaOtaProvisionStatus(status));
+    return {};
+}
+
+Return<void> RadioIndication::currentEmergencyNumberList(
+        V1_0::RadioIndicationType type, const hidl_vec<V1_4::EmergencyNumber>& emergencyNumbers) {
+    LOG_CALL << type;
+    voiceCb()->currentEmergencyNumberList(toAidl(type), toAidl(emergencyNumbers));
+    return {};
+}
+
+Return<void> RadioIndication::enterEmergencyCallbackMode(V1_0::RadioIndicationType type) {
+    LOG_CALL << type;
+    voiceCb()->enterEmergencyCallbackMode(toAidl(type));
+    return {};
+}
+
+Return<void> RadioIndication::exitEmergencyCallbackMode(V1_0::RadioIndicationType type) {
+    LOG_CALL << type;
+    voiceCb()->exitEmergencyCallbackMode(toAidl(type));
+    return {};
+}
+
+Return<void> RadioIndication::indicateRingbackTone(V1_0::RadioIndicationType type, bool start) {
+    LOG_CALL << type;
+    voiceCb()->indicateRingbackTone(toAidl(type), start);
+    return {};
+}
+
+Return<void> RadioIndication::onSupplementaryServiceIndication(V1_0::RadioIndicationType type,
+                                                               const V1_0::StkCcUnsolSsResult& ss) {
+    LOG_CALL << type;
+    voiceCb()->onSupplementaryServiceIndication(toAidl(type), toAidl(ss));
+    return {};
+}
+
+Return<void> RadioIndication::onUssd(V1_0::RadioIndicationType type, V1_0::UssdModeType modeType,
+                                     const hidl_string& msg) {
+    LOG_CALL << type;
+    voiceCb()->onUssd(toAidl(type), aidl::UssdModeType(modeType), msg);
+    return {};
+}
+
+Return<void> RadioIndication::resendIncallMute(V1_0::RadioIndicationType type) {
+    LOG_CALL << type;
+    voiceCb()->resendIncallMute(toAidl(type));
+    return {};
+}
+
+Return<void> RadioIndication::srvccStateNotify(V1_0::RadioIndicationType type,
+                                               V1_0::SrvccState state) {
+    LOG_CALL << type;
+    voiceCb()->srvccStateNotify(toAidl(type), aidl::SrvccState(state));
+    return {};
+}
+
+Return<void> RadioIndication::stkCallControlAlphaNotify(V1_0::RadioIndicationType type,
+                                                        const hidl_string& alpha) {
+    LOG_CALL << type;
+    voiceCb()->stkCallControlAlphaNotify(toAidl(type), alpha);
+    return {};
+}
+
+Return<void> RadioIndication::stkCallSetup(V1_0::RadioIndicationType type, int64_t timeout) {
+    LOG_CALL << type;
+    voiceCb()->stkCallSetup(toAidl(type), timeout);
+    return {};
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/voice/RadioResponse-voice.cpp b/radio/aidl/compat/libradiocompat/voice/RadioResponse-voice.cpp
new file mode 100644
index 0000000..5307e11
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/voice/RadioResponse-voice.cpp
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libradiocompat/RadioResponse.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "VoiceResponse"
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::voice;
+
+void RadioResponse::setResponseFunction(std::shared_ptr<aidl::IRadioVoiceResponse> voiceCb) {
+    mVoiceCb = voiceCb;
+}
+
+std::shared_ptr<aidl::IRadioVoiceResponse> RadioResponse::voiceCb() {
+    return mVoiceCb.get();
+}
+
+Return<void> RadioResponse::acceptCallResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    voiceCb()->acceptCallResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::cancelPendingUssdResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    voiceCb()->cancelPendingUssdResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::conferenceResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    voiceCb()->conferenceResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::dialResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    voiceCb()->dialResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::emergencyDialResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    voiceCb()->emergencyDialResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::exitEmergencyCallbackModeResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    voiceCb()->exitEmergencyCallbackModeResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::explicitCallTransferResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    voiceCb()->explicitCallTransferResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::getCallForwardStatusResponse(
+        const V1_0::RadioResponseInfo& info, const hidl_vec<V1_0::CallForwardInfo>& callFwdInfos) {
+    LOG_CALL << info.serial;
+    voiceCb()->getCallForwardStatusResponse(toAidl(info), toAidl(callFwdInfos));
+    return {};
+}
+
+Return<void> RadioResponse::getCallWaitingResponse(const V1_0::RadioResponseInfo& info, bool enable,
+                                                   int32_t serviceClass) {
+    LOG_CALL << info.serial;
+    voiceCb()->getCallWaitingResponse(toAidl(info), enable, serviceClass);
+    return {};
+}
+
+Return<void> RadioResponse::getClipResponse(const V1_0::RadioResponseInfo& info,
+                                            V1_0::ClipStatus status) {
+    LOG_CALL << info.serial;
+    voiceCb()->getClipResponse(toAidl(info), aidl::ClipStatus(status));
+    return {};
+}
+
+Return<void> RadioResponse::getClirResponse(const V1_0::RadioResponseInfo& info, int32_t n,
+                                            int32_t m) {
+    LOG_CALL << info.serial;
+    voiceCb()->getClirResponse(toAidl(info), n, m);
+    return {};
+}
+
+Return<void> RadioResponse::getCurrentCallsResponse(const V1_0::RadioResponseInfo& info,
+                                                    const hidl_vec<V1_0::Call>& calls) {
+    LOG_CALL << info.serial;
+    voiceCb()->getCurrentCallsResponse(toAidl(info), toAidl(calls));
+    return {};
+}
+
+Return<void> RadioResponse::getCurrentCallsResponse_1_2(const V1_0::RadioResponseInfo& info,
+                                                        const hidl_vec<V1_2::Call>& calls) {
+    LOG_CALL << info.serial;
+    voiceCb()->getCurrentCallsResponse(toAidl(info), toAidl(calls));
+    return {};
+}
+
+Return<void> RadioResponse::getCurrentCallsResponse_1_6(const V1_6::RadioResponseInfo& info,
+                                                        const hidl_vec<V1_6::Call>& calls) {
+    LOG_CALL << info.serial;
+    voiceCb()->getCurrentCallsResponse(toAidl(info), toAidl(calls));
+    return {};
+}
+
+Return<void> RadioResponse::getLastCallFailCauseResponse(
+        const V1_0::RadioResponseInfo& info, const V1_0::LastCallFailCauseInfo& failCauseinfo) {
+    LOG_CALL << info.serial;
+    voiceCb()->getLastCallFailCauseResponse(toAidl(info), toAidl(failCauseinfo));
+    return {};
+}
+
+Return<void> RadioResponse::getMuteResponse(const V1_0::RadioResponseInfo& info, bool enable) {
+    LOG_CALL << info.serial;
+    voiceCb()->getMuteResponse(toAidl(info), enable);
+    return {};
+}
+
+Return<void> RadioResponse::getPreferredVoicePrivacyResponse(const V1_0::RadioResponseInfo& info,
+                                                             bool enable) {
+    LOG_CALL << info.serial;
+    voiceCb()->getPreferredVoicePrivacyResponse(toAidl(info), enable);
+    return {};
+}
+
+Return<void> RadioResponse::getTTYModeResponse(const V1_0::RadioResponseInfo& info,
+                                               V1_0::TtyMode mode) {
+    LOG_CALL << info.serial;
+    voiceCb()->getTtyModeResponse(toAidl(info), aidl::TtyMode(mode));
+    return {};
+}
+
+Return<void> RadioResponse::handleStkCallSetupRequestFromSimResponse(
+        const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    voiceCb()->handleStkCallSetupRequestFromSimResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::hangupConnectionResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    voiceCb()->hangupConnectionResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::hangupForegroundResumeBackgroundResponse(
+        const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    voiceCb()->hangupForegroundResumeBackgroundResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::hangupWaitingOrBackgroundResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    voiceCb()->hangupWaitingOrBackgroundResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::rejectCallResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    voiceCb()->rejectCallResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::sendBurstDtmfResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    voiceCb()->sendBurstDtmfResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::sendCDMAFeatureCodeResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    voiceCb()->sendCdmaFeatureCodeResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::sendDtmfResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    voiceCb()->sendDtmfResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::sendUssdResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    voiceCb()->sendUssdResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::separateConnectionResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    voiceCb()->separateConnectionResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setCallForwardResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    voiceCb()->setCallForwardResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setCallWaitingResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    voiceCb()->setCallWaitingResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setClirResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    voiceCb()->setClirResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setMuteResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    voiceCb()->setMuteResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setPreferredVoicePrivacyResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    voiceCb()->setPreferredVoicePrivacyResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::setTTYModeResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    voiceCb()->setTtyModeResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::startDtmfResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    voiceCb()->startDtmfResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::stopDtmfResponse(const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    voiceCb()->stopDtmfResponse(toAidl(info));
+    return {};
+}
+
+Return<void> RadioResponse::switchWaitingOrHoldingAndActiveResponse(
+        const V1_0::RadioResponseInfo& info) {
+    LOG_CALL << info.serial;
+    voiceCb()->switchWaitingOrHoldingAndActiveResponse(toAidl(info));
+    return {};
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/voice/RadioVoice.cpp b/radio/aidl/compat/libradiocompat/voice/RadioVoice.cpp
new file mode 100644
index 0000000..9088f01
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/voice/RadioVoice.cpp
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libradiocompat/RadioVoice.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+#include "structs.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "Voice"
+
+namespace android::hardware::radio::compat {
+
+using ::ndk::ScopedAStatus;
+namespace aidl = ::aidl::android::hardware::radio::voice;
+constexpr auto ok = &ScopedAStatus::ok;
+
+std::shared_ptr<aidl::IRadioVoiceResponse> RadioVoice::respond() {
+    return mCallbackManager->response().voiceCb();
+}
+
+ScopedAStatus RadioVoice::acceptCall(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->acceptCall(serial);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::cancelPendingUssd(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->cancelPendingUssd(serial);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::conference(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->conference(serial);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::dial(int32_t serial, const aidl::Dial& dialInfo) {
+    LOG_CALL << serial;
+    mHal1_5->dial(serial, toHidl(dialInfo));
+    return ok();
+}
+
+ScopedAStatus RadioVoice::emergencyDial(  //
+        int32_t serial, const aidl::Dial& info, int32_t categories,
+        const std::vector<std::string>& urns, aidl::EmergencyCallRouting routing,
+        bool knownUserIntentEmerg, bool isTesting) {
+    LOG_CALL << serial;
+    if (mHal1_6) {
+        mHal1_6->emergencyDial_1_6(  //
+                serial, toHidl(info), toHidlBitfield<V1_4::EmergencyServiceCategory>(categories),
+                toHidl(urns), V1_4::EmergencyCallRouting(routing), knownUserIntentEmerg, isTesting);
+    } else {
+        mHal1_5->emergencyDial(  //
+                serial, toHidl(info), toHidlBitfield<V1_4::EmergencyServiceCategory>(categories),
+                toHidl(urns), V1_4::EmergencyCallRouting(routing), knownUserIntentEmerg, isTesting);
+    }
+    return ok();
+}
+
+ScopedAStatus RadioVoice::exitEmergencyCallbackMode(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->exitEmergencyCallbackMode(serial);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::explicitCallTransfer(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->explicitCallTransfer(serial);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::getCallForwardStatus(int32_t serial,
+                                               const aidl::CallForwardInfo& callInfo) {
+    LOG_CALL << serial;
+    mHal1_5->getCallForwardStatus(serial, toHidl(callInfo));
+    return ok();
+}
+
+ScopedAStatus RadioVoice::getCallWaiting(int32_t serial, int32_t serviceClass) {
+    LOG_CALL << serial;
+    mHal1_5->getCallWaiting(serial, serviceClass);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::getClip(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getClip(serial);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::getClir(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getClir(serial);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::getCurrentCalls(int32_t serial) {
+    LOG_CALL << serial;
+    if (mHal1_6) {
+        mHal1_6->getCurrentCalls_1_6(serial);
+    } else {
+        mHal1_5->getCurrentCalls(serial);
+    }
+    return ok();
+}
+
+ScopedAStatus RadioVoice::getLastCallFailCause(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getLastCallFailCause(serial);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::getMute(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getMute(serial);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::getPreferredVoicePrivacy(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getPreferredVoicePrivacy(serial);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::getTtyMode(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->getTTYMode(serial);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::handleStkCallSetupRequestFromSim(int32_t serial, bool accept) {
+    LOG_CALL << serial;
+    mHal1_5->handleStkCallSetupRequestFromSim(serial, accept);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::hangup(int32_t serial, int32_t gsmIndex) {
+    LOG_CALL << serial;
+    mHal1_5->hangup(serial, gsmIndex);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::hangupForegroundResumeBackground(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->hangupForegroundResumeBackground(serial);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::hangupWaitingOrBackground(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->hangupWaitingOrBackground(serial);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::isVoNrEnabled(int32_t serial) {
+    LOG_CALL << serial;
+    respond()->isVoNrEnabledResponse(notSupported(serial), false);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::rejectCall(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->rejectCall(serial);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::responseAcknowledgement() {
+    LOG_CALL;
+    mHal1_5->responseAcknowledgement();
+    return ok();
+}
+
+ScopedAStatus RadioVoice::sendBurstDtmf(int32_t serial, const std::string& dtmf, int32_t on,
+                                        int32_t off) {
+    LOG_CALL << serial;
+    mHal1_5->sendBurstDtmf(serial, dtmf, on, off);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::sendCdmaFeatureCode(int32_t serial, const std::string& featureCode) {
+    LOG_CALL << serial;
+    mHal1_5->sendCDMAFeatureCode(serial, featureCode);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::sendDtmf(int32_t serial, const std::string& s) {
+    LOG_CALL << serial;
+    mHal1_5->sendDtmf(serial, s);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::sendUssd(int32_t serial, const std::string& ussd) {
+    LOG_CALL << serial << ' ' << ussd;
+    mHal1_5->sendUssd(serial, ussd);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::separateConnection(int32_t serial, int32_t gsmIndex) {
+    LOG_CALL << serial;
+    mHal1_5->separateConnection(serial, gsmIndex);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::setCallForward(int32_t serial, const aidl::CallForwardInfo& callInfo) {
+    LOG_CALL << serial;
+    mHal1_5->setCallForward(serial, toHidl(callInfo));
+    return ok();
+}
+
+ScopedAStatus RadioVoice::setCallWaiting(int32_t serial, bool enable, int32_t serviceClass) {
+    LOG_CALL << serial;
+    mHal1_5->setCallWaiting(serial, enable, serviceClass);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::setClir(int32_t serial, int32_t status) {
+    LOG_CALL << serial;
+    mHal1_5->setClir(serial, status);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::setMute(int32_t serial, bool enable) {
+    LOG_CALL << serial;
+    mHal1_5->setMute(serial, enable);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::setPreferredVoicePrivacy(int32_t serial, bool enable) {
+    LOG_CALL << serial;
+    mHal1_5->setPreferredVoicePrivacy(serial, enable);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::setResponseFunctions(
+        const std::shared_ptr<aidl::IRadioVoiceResponse>& response,
+        const std::shared_ptr<aidl::IRadioVoiceIndication>& indication) {
+    LOG_CALL << response << ' ' << indication;
+    mCallbackManager->setResponseFunctions(response, indication);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::setTtyMode(int32_t serial, aidl::TtyMode mode) {
+    LOG_CALL << serial;
+    mHal1_5->setTTYMode(serial, V1_0::TtyMode(mode));
+    return ok();
+}
+
+ndk::ScopedAStatus RadioVoice::setVoNrEnabled(int32_t serial, [[maybe_unused]] bool enable) {
+    LOG_CALL << serial;
+    // Note: a workaround for older HALs could also be setting persist.radio.is_vonr_enabled_
+    respond()->setVoNrEnabledResponse(notSupported(serial));
+    return ok();
+}
+
+ScopedAStatus RadioVoice::startDtmf(int32_t serial, const std::string& s) {
+    LOG_CALL << serial;
+    mHal1_5->startDtmf(serial, s);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::stopDtmf(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->stopDtmf(serial);
+    return ok();
+}
+
+ScopedAStatus RadioVoice::switchWaitingOrHoldingAndActive(int32_t serial) {
+    LOG_CALL << serial;
+    mHal1_5->switchWaitingOrHoldingAndActive(serial);
+    return ok();
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/voice/structs.cpp b/radio/aidl/compat/libradiocompat/voice/structs.cpp
new file mode 100644
index 0000000..254ea20
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/voice/structs.cpp
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "structs.h"
+
+#include "commonStructs.h"
+
+#include "collections.h"
+
+#include <android-base/logging.h>
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::voice;
+
+V1_0::Dial toHidl(const aidl::Dial& info) {
+    return {
+            .address = info.address,
+            .clir = 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},
+            .uusData = info.uusData,
+    };
+}
+
+aidl::CallForwardInfo toAidl(const V1_0::CallForwardInfo& info) {
+    return {
+            .status = static_cast<int32_t>(info.status),
+            .reason = info.reason,
+            .serviceClass = info.serviceClass,
+            .toa = info.toa,
+            .number = info.number,
+            .timeSeconds = info.timeSeconds,
+    };
+}
+
+V1_0::CallForwardInfo toHidl(const aidl::CallForwardInfo& info) {
+    return {
+            .status = V1_0::CallForwardInfoStatus{info.status},
+            .reason = info.reason,
+            .serviceClass = info.serviceClass,
+            .toa = info.toa,
+            .number = info.number,
+            .timeSeconds = info.timeSeconds,
+    };
+}
+
+aidl::CdmaSignalInfoRecord toAidl(const V1_0::CdmaSignalInfoRecord& record) {
+    return {
+            .isPresent = record.isPresent,
+            .signalType = record.signalType,
+            .alertPitch = record.alertPitch,
+            .signal = record.signal,
+    };
+}
+
+aidl::CdmaCallWaiting toAidl(const V1_0::CdmaCallWaiting& call) {
+    return {
+            .number = call.number,
+            .numberPresentation = static_cast<int32_t>(call.numberPresentation),
+            .name = call.name,
+            .signalInfoRecord = toAidl(call.signalInfoRecord),
+            .numberType = static_cast<int32_t>(call.numberType),
+            .numberPlan = static_cast<int32_t>(call.numberPlan),
+    };
+}
+
+aidl::CdmaInformationRecord toAidl(const V1_0::CdmaInformationRecord& record) {
+    return {
+            .name = static_cast<int32_t>(record.name),
+            .display = toAidl(record.display),
+            .number = toAidl(record.number),
+            .signal = toAidl(record.signal),
+            .redir = toAidl(record.redir),
+            .lineCtrl = toAidl(record.lineCtrl),
+            .clir = toAidl(record.clir),
+            .audioCtrl = toAidl(record.audioCtrl),
+    };
+}
+
+aidl::CdmaDisplayInfoRecord toAidl(const V1_0::CdmaDisplayInfoRecord& record) {
+    return {
+            .alphaBuf = record.alphaBuf,
+    };
+}
+
+aidl::CdmaNumberInfoRecord toAidl(const V1_0::CdmaNumberInfoRecord& record) {
+    return {
+            .number = record.number,
+            .numberType = static_cast<int8_t>(record.numberType),
+            .numberPlan = static_cast<int8_t>(record.numberPlan),
+            .pi = static_cast<int8_t>(record.pi),
+            .si = static_cast<int8_t>(record.si),
+    };
+}
+
+aidl::CdmaRedirectingNumberInfoRecord toAidl(const V1_0::CdmaRedirectingNumberInfoRecord& record) {
+    return {
+            .redirectingNumber = toAidl(record.redirectingNumber),
+            .redirectingReason = static_cast<int32_t>(record.redirectingReason),
+    };
+}
+
+aidl::CdmaLineControlInfoRecord toAidl(const V1_0::CdmaLineControlInfoRecord& record) {
+    return {
+            .lineCtrlPolarityIncluded = static_cast<int8_t>(record.lineCtrlPolarityIncluded),
+            .lineCtrlToggle = static_cast<int8_t>(record.lineCtrlToggle),
+            .lineCtrlReverse = static_cast<int8_t>(record.lineCtrlReverse),
+            .lineCtrlPowerDenial = static_cast<int8_t>(record.lineCtrlPowerDenial),
+    };
+}
+
+aidl::CdmaT53ClirInfoRecord toAidl(const V1_0::CdmaT53ClirInfoRecord& record) {
+    return {
+            .cause = static_cast<int8_t>(record.cause),
+    };
+}
+
+aidl::CdmaT53AudioControlInfoRecord toAidl(const V1_0::CdmaT53AudioControlInfoRecord& record) {
+    return {
+            .upLink = static_cast<int8_t>(record.upLink),
+            .downLink = static_cast<int8_t>(record.downLink),
+    };
+}
+
+aidl::EmergencyNumber toAidl(const V1_4::EmergencyNumber& num) {
+    return {
+            .number = num.number,
+            .mcc = num.mcc,
+            .mnc = num.mnc,
+            .categories = num.categories,
+            .urns = toAidl(num.urns),
+            .sources = num.sources,
+    };
+}
+
+aidl::StkCcUnsolSsResult toAidl(const V1_0::StkCcUnsolSsResult& res) {
+    return {
+            .serviceType = static_cast<int32_t>(res.serviceType),
+            .requestType = static_cast<int32_t>(res.requestType),
+            .teleserviceType = static_cast<int32_t>(res.teleserviceType),
+            .serviceClass = res.serviceClass,
+            .result = toAidl(res.result),
+            .ssInfo = toAidl(res.ssInfo),
+            .cfData = toAidl(res.cfData),
+    };
+}
+
+aidl::SsInfoData toAidl(const V1_0::SsInfoData& info) {
+    return {
+            .ssInfo = info.ssInfo,
+    };
+}
+
+aidl::CfData toAidl(const V1_0::CfData& data) {
+    return {
+            .cfInfo = toAidl(data.cfInfo),
+    };
+}
+
+aidl::Call toAidl(const V1_0::Call& call) {
+    return toAidl(V1_2::Call{call, {}});
+}
+
+aidl::Call toAidl(const V1_2::Call& call) {
+    return toAidl(V1_6::Call{call, {}});
+}
+
+aidl::Call toAidl(const V1_6::Call& call) {
+    return {
+            .state = static_cast<int32_t>(call.base.base.state),
+            .index = call.base.base.index,
+            .toa = call.base.base.toa,
+            .isMpty = call.base.base.isMpty,
+            .isMT = call.base.base.isMT,
+            .als = static_cast<int8_t>(call.base.base.als),
+            .isVoice = call.base.base.isVoice,
+            .isVoicePrivacy = call.base.base.isVoicePrivacy,
+            .number = call.base.base.number,
+            .numberPresentation = static_cast<int32_t>(call.base.base.numberPresentation),
+            .name = call.base.base.name,
+            .namePresentation = static_cast<int32_t>(call.base.base.namePresentation),
+            .uusInfo = toAidl(call.base.base.uusInfo),
+            .audioQuality = aidl::AudioQuality(call.base.audioQuality),
+            .forwardedNumber = call.forwardedNumber,
+    };
+}
+
+aidl::UusInfo toAidl(const V1_0::UusInfo& info) {
+    return {
+            .uusType = static_cast<int32_t>(info.uusType),
+            .uusDcs = static_cast<int32_t>(info.uusDcs),
+            .uusData = info.uusData,
+    };
+}
+
+aidl::LastCallFailCauseInfo toAidl(const V1_0::LastCallFailCauseInfo& info) {
+    return {
+            .causeCode = aidl::LastCallFailCause(info.causeCode),
+            .vendorCause = info.vendorCause,
+    };
+}
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/voice/structs.h b/radio/aidl/compat/libradiocompat/voice/structs.h
new file mode 100644
index 0000000..b55a089
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/voice/structs.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <aidl/android/hardware/radio/voice/Call.h>
+#include <aidl/android/hardware/radio/voice/CallForwardInfo.h>
+#include <aidl/android/hardware/radio/voice/CdmaCallWaiting.h>
+#include <aidl/android/hardware/radio/voice/CdmaDisplayInfoRecord.h>
+#include <aidl/android/hardware/radio/voice/CdmaInformationRecord.h>
+#include <aidl/android/hardware/radio/voice/CdmaLineControlInfoRecord.h>
+#include <aidl/android/hardware/radio/voice/CdmaNumberInfoRecord.h>
+#include <aidl/android/hardware/radio/voice/CdmaRedirectingNumberInfoRecord.h>
+#include <aidl/android/hardware/radio/voice/CdmaSignalInfoRecord.h>
+#include <aidl/android/hardware/radio/voice/CdmaT53AudioControlInfoRecord.h>
+#include <aidl/android/hardware/radio/voice/CdmaT53ClirInfoRecord.h>
+#include <aidl/android/hardware/radio/voice/CfData.h>
+#include <aidl/android/hardware/radio/voice/Dial.h>
+#include <aidl/android/hardware/radio/voice/EmergencyNumber.h>
+#include <aidl/android/hardware/radio/voice/LastCallFailCauseInfo.h>
+#include <aidl/android/hardware/radio/voice/SsInfoData.h>
+#include <aidl/android/hardware/radio/voice/StkCcUnsolSsResult.h>
+#include <aidl/android/hardware/radio/voice/UusInfo.h>
+#include <android/hardware/radio/1.6/types.h>
+
+namespace android::hardware::radio::compat {
+
+V1_0::Dial toHidl(const ::aidl::android::hardware::radio::voice::Dial& info);
+
+V1_0::UusInfo toHidl(const ::aidl::android::hardware::radio::voice::UusInfo& info);
+
+::aidl::android::hardware::radio::voice::CallForwardInfo toAidl(const V1_0::CallForwardInfo& info);
+V1_0::CallForwardInfo toHidl(const ::aidl::android::hardware::radio::voice::CallForwardInfo& info);
+
+::aidl::android::hardware::radio::voice::CdmaSignalInfoRecord  //
+toAidl(const V1_0::CdmaSignalInfoRecord& record);
+
+::aidl::android::hardware::radio::voice::CdmaCallWaiting toAidl(const V1_0::CdmaCallWaiting& call);
+
+::aidl::android::hardware::radio::voice::CdmaInformationRecord  //
+toAidl(const V1_0::CdmaInformationRecord& record);
+
+::aidl::android::hardware::radio::voice::CdmaDisplayInfoRecord  //
+toAidl(const V1_0::CdmaDisplayInfoRecord& record);
+
+::aidl::android::hardware::radio::voice::CdmaNumberInfoRecord  //
+toAidl(const V1_0::CdmaNumberInfoRecord& record);
+
+::aidl::android::hardware::radio::voice::CdmaRedirectingNumberInfoRecord  //
+toAidl(const V1_0::CdmaRedirectingNumberInfoRecord& record);
+
+::aidl::android::hardware::radio::voice::CdmaLineControlInfoRecord  //
+toAidl(const V1_0::CdmaLineControlInfoRecord& record);
+
+::aidl::android::hardware::radio::voice::CdmaT53ClirInfoRecord  //
+toAidl(const V1_0::CdmaT53ClirInfoRecord& record);
+
+::aidl::android::hardware::radio::voice::CdmaT53AudioControlInfoRecord  //
+toAidl(const V1_0::CdmaT53AudioControlInfoRecord& record);
+
+::aidl::android::hardware::radio::voice::EmergencyNumber toAidl(const V1_4::EmergencyNumber& num);
+
+::aidl::android::hardware::radio::voice::StkCcUnsolSsResult  //
+toAidl(const V1_0::StkCcUnsolSsResult& res);
+
+::aidl::android::hardware::radio::voice::SsInfoData toAidl(const V1_0::SsInfoData& info);
+
+::aidl::android::hardware::radio::voice::CfData toAidl(const V1_0::CfData& data);
+
+::aidl::android::hardware::radio::voice::Call toAidl(const V1_0::Call& call);
+::aidl::android::hardware::radio::voice::Call toAidl(const V1_2::Call& call);
+::aidl::android::hardware::radio::voice::Call toAidl(const V1_6::Call& call);
+
+::aidl::android::hardware::radio::voice::UusInfo toAidl(const V1_0::UusInfo& info);
+
+::aidl::android::hardware::radio::voice::LastCallFailCauseInfo  //
+toAidl(const V1_0::LastCallFailCauseInfo& info);
+
+}  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/service/Android.bp b/radio/aidl/compat/service/Android.bp
new file mode 100644
index 0000000..52eb71f
--- /dev/null
+++ b/radio/aidl/compat/service/Android.bp
@@ -0,0 +1,64 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+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.radio-service.compat",
+    relative_install_path: "hw",
+    init_rc: ["radio-compat.rc"],
+    vintf_fragments: ["radio-compat.xml"],
+    vendor: true,
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
+    ],
+    shared_libs: [
+        "android.hardware.radio-library.compat",
+        "android.hardware.radio.config-V1-ndk",
+        "android.hardware.radio.config@1.0",
+        "android.hardware.radio.config@1.1",
+        "android.hardware.radio.config@1.2",
+        "android.hardware.radio.config@1.3",
+        "android.hardware.radio.data-V1-ndk",
+        "android.hardware.radio.messaging-V1-ndk",
+        "android.hardware.radio.modem-V1-ndk",
+        "android.hardware.radio.network-V1-ndk",
+        "android.hardware.radio.sim-V1-ndk",
+        "android.hardware.radio.voice-V1-ndk",
+        "android.hardware.radio@1.0",
+        "android.hardware.radio@1.1",
+        "android.hardware.radio@1.2",
+        "android.hardware.radio@1.3",
+        "android.hardware.radio@1.4",
+        "android.hardware.radio@1.5",
+        "android.hardware.radio@1.6",
+        "libbase",
+        "libbinder_ndk",
+        "libhidlbase",
+        "libutils",
+    ],
+    srcs: [
+        "hidl-utils.cpp",
+        "service.cpp",
+    ],
+}
diff --git a/radio/aidl/compat/service/hidl-utils.cpp b/radio/aidl/compat/service/hidl-utils.cpp
new file mode 100644
index 0000000..fc0d54d
--- /dev/null
+++ b/radio/aidl/compat/service/hidl-utils.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "hidl-utils.h"
+
+#include <android-base/logging.h>
+#include <android/hidl/manager/1.2/IServiceManager.h>
+
+namespace android::hardware::hidl_utils {
+
+class HalDeathRecipient : public hidl_death_recipient {
+    void serviceDied(uint64_t /* cookie */, const wp<hidl::base::V1_0::IBase>& /* who */) override {
+        LOG(FATAL) << "One of the linked HALs died. Restarting...";
+    }
+};
+
+static const auto gHalDeathRecipient = sp<HalDeathRecipient>::make();
+
+void linkDeathToDeath(sp<::android::hidl::base::V1_0::IBase> hal) {
+    const auto linkStatus = hal->linkToDeath(gHalDeathRecipient, 0);
+    CHECK(linkStatus.withDefault(false)) << "Failed to link to HAL death";
+}
+
+hidl_vec<hidl_string> listManifestByInterface(const char* descriptor) {
+    auto manager = hidl::manager::V1_2::IServiceManager::getService();
+    hidl_vec<hidl_string> services;
+    manager->listManifestByInterface(descriptor, hidl_utils::fill(&services));
+    CHECK_GT(services.size(), 0u) << "No " << descriptor
+                                  << " services in manifest (missing privileges?)" << std::endl;
+    return services;
+}
+
+}  // namespace android::hardware::hidl_utils
diff --git a/radio/aidl/compat/service/hidl-utils.h b/radio/aidl/compat/service/hidl-utils.h
new file mode 100644
index 0000000..be3386f
--- /dev/null
+++ b/radio/aidl/compat/service/hidl-utils.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/hidl/base/1.0/IBase.h>
+
+#include <functional>
+
+namespace android::hardware::hidl_utils {
+
+/**
+ * Helper functor to fetch results from multi-return HIDL calls.
+ * It's meant to be used in place of _hidl_cb callbacks.
+ *
+ * Please note extracting these return variables outside of the callback scope requires making
+ * a copy of each return variable. This may be costly for frequently called HIDL methods with
+ * non-negligible return object size. Please be cautious about performance when using this.
+ *
+ * Example usage:
+ *     Result result;
+ *     sp<ISomeInterface> iface;
+ *     hidlObject->someMethod(arg1, arg2, hidl_utils::fill(&result, &iface)).assertOk();
+ *     // use result and iface
+ */
+template <typename... T>
+struct fill : public std::function<void(const T&...)> {
+    /**
+     * Create _hidl_cb functor that copies the call arguments to specified pointers.
+     *
+     * \param args... Targets to copy the call arguments to
+     */
+    fill(T*... args) : mTargets(args...) {}
+
+    void operator()(const T&... args) { copy<0, T...>(args...); }
+
+  private:
+    std::tuple<T*...> mTargets;
+
+    template <int Pos, typename First>
+    inline void copy(const First& first) {
+        *std::get<Pos>(mTargets) = first;
+    }
+
+    template <int Pos, typename First, typename... Rest>
+    inline void copy(const First& first, const Rest&... rest) {
+        *std::get<Pos>(mTargets) = first;
+        copy<Pos + 1, Rest...>(rest...);
+    }
+};
+
+/**
+ * Link to a given HALs death and restart the current process in such a case.
+ * \param hal HAL to which death to link
+ */
+void linkDeathToDeath(sp<hidl::base::V1_0::IBase> hal);
+
+/**
+ * List HAL instances of a given interface.
+ *
+ * \descriptor HIDL HAL descriptor
+ */
+hidl_vec<hidl_string> listManifestByInterface(const char* descriptor);
+
+}  // namespace android::hardware::hidl_utils
diff --git a/radio/aidl/compat/service/radio-compat.rc b/radio/aidl/compat/service/radio-compat.rc
new file mode 100644
index 0000000..a159876
--- /dev/null
+++ b/radio/aidl/compat/service/radio-compat.rc
@@ -0,0 +1,4 @@
+service vendor.radio-compat /vendor/bin/hw/android.hardware.radio-service.compat
+    class hal
+    user nobody
+    group system
diff --git a/radio/aidl/compat/service/radio-compat.xml b/radio/aidl/compat/service/radio-compat.xml
new file mode 100644
index 0000000..a7089e6
--- /dev/null
+++ b/radio/aidl/compat/service/radio-compat.xml
@@ -0,0 +1,37 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.radio.config</name>
+        <fqname>IRadioConfig/default</fqname>
+    </hal>
+<!--
+    Instances other than config are configured per-device, depending on the slot count (framework
+    currently supports slot1, slot2 and slot3 instances) and Radio HALs device wishes to provide.
+    You can either copy the following tags to device manifest or simply uncomment them here for
+    quick testing.
+
+    <hal format="aidl">
+        <name>android.hardware.radio.data</name>
+        <fqname>IRadioData/slot1</fqname>
+    </hal>
+    <hal format="aidl">
+        <name>android.hardware.radio.messaging</name>
+        <fqname>IRadioMessaging/slot1</fqname>
+    </hal>
+    <hal format="aidl">
+        <name>android.hardware.radio.modem</name>
+        <fqname>IRadioModem/slot1</fqname>
+    </hal>
+    <hal format="aidl">
+        <name>android.hardware.radio.network</name>
+        <fqname>IRadioNetwork/slot1</fqname>
+    </hal>
+    <hal format="aidl">
+        <name>android.hardware.radio.sim</name>
+        <fqname>IRadioSim/slot1</fqname>
+    </hal>
+    <hal format="aidl">
+        <name>android.hardware.radio.voice</name>
+        <fqname>IRadioVoice/slot1</fqname>
+    </hal>
+-->
+</manifest>
diff --git a/radio/aidl/compat/service/service.cpp b/radio/aidl/compat/service/service.cpp
new file mode 100644
index 0000000..8af05de
--- /dev/null
+++ b/radio/aidl/compat/service/service.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "hidl-utils.h"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <libradiocompat/CallbackManager.h>
+#include <libradiocompat/RadioConfig.h>
+#include <libradiocompat/RadioData.h>
+#include <libradiocompat/RadioMessaging.h>
+#include <libradiocompat/RadioModem.h>
+#include <libradiocompat/RadioNetwork.h>
+#include <libradiocompat/RadioSim.h>
+#include <libradiocompat/RadioVoice.h>
+
+namespace android::hardware::radio::service {
+
+using namespace std::string_literals;
+
+static std::vector<std::shared_ptr<ndk::ICInterface>> gPublishedHals;
+
+template <typename T>
+static void publishRadioHal(std::shared_ptr<compat::DriverContext> ctx, sp<V1_5::IRadio> hidlHal,
+                            std::shared_ptr<compat::CallbackManager> cm, const std::string& slot) {
+    const auto instance = T::descriptor + "/"s + slot;
+    if (!AServiceManager_isDeclared(instance.c_str())) {
+        LOG(INFO) << instance << " is not declared in VINTF (this may be intentional)";
+        return;
+    }
+    LOG(DEBUG) << "Publishing " << instance;
+
+    auto aidlHal = ndk::SharedRefBase::make<T>(ctx, hidlHal, cm);
+    gPublishedHals.push_back(aidlHal);
+    const auto status = AServiceManager_addService(aidlHal->asBinder().get(), instance.c_str());
+    CHECK_EQ(status, STATUS_OK);
+}
+
+static void publishRadio(std::string slot) {
+    auto radioHidl = V1_5::IRadio::getService(slot);
+    CHECK(radioHidl) << "HIDL IRadio not present in VINTF";
+
+    hidl_utils::linkDeathToDeath(radioHidl);
+
+    auto context = std::make_shared<compat::DriverContext>();
+    auto callbackMgr = std::make_shared<compat::CallbackManager>(context, radioHidl);
+
+    publishRadioHal<compat::RadioData>(context, radioHidl, callbackMgr, slot);
+    publishRadioHal<compat::RadioMessaging>(context, radioHidl, callbackMgr, slot);
+    publishRadioHal<compat::RadioModem>(context, radioHidl, callbackMgr, slot);
+    publishRadioHal<compat::RadioNetwork>(context, radioHidl, callbackMgr, slot);
+    publishRadioHal<compat::RadioSim>(context, radioHidl, callbackMgr, slot);
+    publishRadioHal<compat::RadioVoice>(context, radioHidl, callbackMgr, slot);
+}
+
+static void publishRadioConfig() {
+    auto hidlHal = config::V1_1::IRadioConfig::getService();
+    CHECK(hidlHal) << "HIDL IRadioConfig not present in VINTF";
+
+    hidl_utils::linkDeathToDeath(hidlHal);
+
+    auto aidlHal = ndk::SharedRefBase::make<compat::RadioConfig>(hidlHal);
+    gPublishedHals.push_back(aidlHal);
+    const auto instance = compat::RadioConfig::descriptor + "/default"s;
+    const auto status = AServiceManager_addService(aidlHal->asBinder().get(), instance.c_str());
+    CHECK_EQ(status, STATUS_OK);
+}
+
+static void main() {
+    base::InitLogging(nullptr, base::LogdLogger(base::RADIO));
+    base::SetDefaultTag("radiocompat");
+    base::SetMinimumLogSeverity(base::VERBOSE);
+    LOG(DEBUG) << "Radio HAL compat service starting...";
+
+    publishRadioConfig();
+
+    const auto slots = hidl_utils::listManifestByInterface(V1_0::IRadio::descriptor);
+    LOG(INFO) << "Found " << slots.size() << " slot(s)";
+    for (const auto& slot : slots) {
+        publishRadio(slot);
+    }
+
+    LOG(DEBUG) << "Radio HAL compat service is operational";
+    ABinderProcess_joinThreadPool();
+    LOG(FATAL) << "Radio HAL compat service has stopped";
+}
+
+}  // namespace android::hardware::radio::service
+
+int main() {
+    android::hardware::radio::service::main();
+    return EXIT_FAILURE;  // should not reach
+}
diff --git a/radio/aidl/vts/Android.bp b/radio/aidl/vts/Android.bp
new file mode 100644
index 0000000..021ee89
--- /dev/null
+++ b/radio/aidl/vts/Android.bp
@@ -0,0 +1,79 @@
+// Copyright 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+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: "VtsHalRadioTargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    tidy_timeout_srcs: [
+        "radio_messaging_test.cpp",
+        "radio_network_test.cpp",
+        "radio_sim_test.cpp",
+        "radio_voice_test.cpp",
+    ],
+    srcs: [
+        "radio_aidl_hal_utils.cpp",
+        "radio_config_indication.cpp",
+        "radio_config_response.cpp",
+        "radio_config_test.cpp",
+        "radio_data_indication.cpp",
+        "radio_data_response.cpp",
+        "radio_data_test.cpp",
+        "radio_messaging_indication.cpp",
+        "radio_messaging_response.cpp",
+        "radio_messaging_test.cpp",
+        "radio_modem_indication.cpp",
+        "radio_modem_response.cpp",
+        "radio_modem_test.cpp",
+        "radio_network_indication.cpp",
+        "radio_network_response.cpp",
+        "radio_network_test.cpp",
+        "radio_sim_indication.cpp",
+        "radio_sim_response.cpp",
+        "radio_sim_test.cpp",
+        "radio_voice_indication.cpp",
+        "radio_voice_response.cpp",
+        "radio_voice_test.cpp",
+        "VtsHalRadioTargetTest.cpp",
+    ],
+    shared_libs: [
+        "libbinder_ndk",
+        "libvintf",
+    ],
+    static_libs: [
+        "android.hardware.radio-V1-ndk",
+        "android.hardware.radio.config-V1-ndk",
+        "android.hardware.radio.data-V1-ndk",
+        "android.hardware.radio.messaging-V1-ndk",
+        "android.hardware.radio.modem-V1-ndk",
+        "android.hardware.radio.network-V1-ndk",
+        "android.hardware.radio.sim-V1-ndk",
+        "android.hardware.radio.voice-V1-ndk",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
diff --git a/radio/aidl/vts/AndroidTest.xml b/radio/aidl/vts/AndroidTest.xml
new file mode 100644
index 0000000..36381d1
--- /dev/null
+++ b/radio/aidl/vts/AndroidTest.xml
@@ -0,0 +1,34 @@
+<?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 VtsHalRadioTargetTest.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-native" />
+
+    <target_preparer class="com.android.tradefed.targetprep.MultiSimPreparer" />
+    <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="VtsHalRadioTargetTest->/data/local/tmp/VtsHalRadioTargetTest" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="native-test-timeout" value="300000" /> <!-- 5 min -->
+        <option name="module-name" value="VtsHalRadioTargetTest" />
+    </test>
+</configuration>
\ No newline at end of file
diff --git a/radio/aidl/vts/OWNERS b/radio/aidl/vts/OWNERS
new file mode 100644
index 0000000..e75c6c8
--- /dev/null
+++ b/radio/aidl/vts/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 20868
+include ../../1.0/vts/OWNERS
+
diff --git a/radio/aidl/vts/VtsHalRadioTargetTest.cpp b/radio/aidl/vts/VtsHalRadioTargetTest.cpp
new file mode 100644
index 0000000..1ebc6af
--- /dev/null
+++ b/radio/aidl/vts/VtsHalRadioTargetTest.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/binder_process.h>
+
+#include "radio_config_utils.h"
+#include "radio_data_utils.h"
+#include "radio_messaging_utils.h"
+#include "radio_modem_utils.h"
+#include "radio_network_utils.h"
+#include "radio_sim_utils.h"
+#include "radio_voice_utils.h"
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioConfigTest);
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, RadioConfigTest,
+        testing::ValuesIn(android::getAidlHalInstanceNames(IRadioConfig::descriptor)),
+        android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioDataTest);
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, RadioDataTest,
+        testing::ValuesIn(android::getAidlHalInstanceNames(IRadioData::descriptor)),
+        android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioMessagingTest);
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, RadioMessagingTest,
+        testing::ValuesIn(android::getAidlHalInstanceNames(IRadioMessaging::descriptor)),
+        android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioModemTest);
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, RadioModemTest,
+        testing::ValuesIn(android::getAidlHalInstanceNames(IRadioModem::descriptor)),
+        android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioNetworkTest);
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, RadioNetworkTest,
+        testing::ValuesIn(android::getAidlHalInstanceNames(IRadioNetwork::descriptor)),
+        android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioSimTest);
+INSTANTIATE_TEST_SUITE_P(PerInstance, RadioSimTest,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(IRadioSim::descriptor)),
+                         android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioVoiceTest);
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, RadioVoiceTest,
+        testing::ValuesIn(android::getAidlHalInstanceNames(IRadioVoice::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/radio/aidl/vts/radio_aidl_hal_utils.cpp b/radio/aidl/vts/radio_aidl_hal_utils.cpp
new file mode 100644
index 0000000..efc4f26
--- /dev/null
+++ b/radio/aidl/vts/radio_aidl_hal_utils.cpp
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "RadioTest"
+
+#include "radio_aidl_hal_utils.h"
+#include <iostream>
+#include "VtsCoreUtil.h"
+#include "radio_config_utils.h"
+#include "radio_sim_utils.h"
+
+#define WAIT_TIMEOUT_PERIOD 75
+
+sim::CardStatus cardStatus = {};
+config::SimSlotStatus slotStatus = {};
+int serial = 0;
+int count_ = 0;
+
+int GetRandomSerialNumber() {
+    return rand();
+}
+
+::testing::AssertionResult CheckAnyOfErrors(RadioError err, std::vector<RadioError> errors,
+                                            CheckFlag flag) {
+    const static std::vector<RadioError> generalErrors = {
+            RadioError::RADIO_NOT_AVAILABLE,   RadioError::NO_MEMORY,
+            RadioError::INTERNAL_ERR,          RadioError::SYSTEM_ERR,
+            RadioError::REQUEST_NOT_SUPPORTED, RadioError::CANCELLED};
+    if (flag == CHECK_GENERAL_ERROR || flag == CHECK_OEM_AND_GENERAL_ERROR) {
+        for (size_t i = 0; i < generalErrors.size(); i++) {
+            if (err == generalErrors[i]) {
+                return testing::AssertionSuccess();
+            }
+        }
+    }
+    if (flag == CHECK_OEM_ERROR || flag == CHECK_OEM_AND_GENERAL_ERROR) {
+        if (err >= RadioError::OEM_ERROR_1 && err <= RadioError::OEM_ERROR_25) {
+            return testing::AssertionSuccess();
+        }
+    }
+    for (size_t i = 0; i < errors.size(); i++) {
+        if (err == errors[i]) {
+            return testing::AssertionSuccess();
+        }
+    }
+    return testing::AssertionFailure() << "RadioError:" + toString(err) + " is returned";
+}
+
+// Runs "pm list features" and attempts to find the specified feature in its output.
+bool deviceSupportsFeature(const char* feature) {
+    bool hasFeature = false;
+    FILE* p = popen("/system/bin/pm list features", "re");
+    if (p) {
+        char* line = NULL;
+        size_t len = 0;
+        while (getline(&line, &len, p) > 0) {
+            if (strstr(line, feature)) {
+                hasFeature = true;
+                break;
+            }
+        }
+        pclose(p);
+    } else {
+        __android_log_print(ANDROID_LOG_FATAL, LOG_TAG, "popen failed: %d", errno);
+        _exit(EXIT_FAILURE);
+    }
+    __android_log_print(ANDROID_LOG_INFO, LOG_TAG, "Feature %s: %ssupported", feature,
+                        hasFeature ? "" : "not ");
+    return hasFeature;
+}
+
+bool isSsSsEnabled() {
+    // Do not use checkSubstringInCommandOutput("getprop persist.radio.multisim.config", "")
+    // until b/148904287 is fixed. We need exact matching instead of partial matching. (i.e.
+    // by definition the empty string "" is a substring of any string).
+    return !isDsDsEnabled() && !isTsTsEnabled();
+}
+
+bool isDsDsEnabled() {
+    return testing::checkSubstringInCommandOutput("getprop persist.radio.multisim.config", "dsds");
+}
+
+bool isTsTsEnabled() {
+    return testing::checkSubstringInCommandOutput("getprop persist.radio.multisim.config", "tsts");
+}
+
+bool isVoiceInService(RegState state) {
+    return RegState::REG_HOME == state || RegState::REG_ROAMING == state;
+}
+
+bool isVoiceEmergencyOnly(RegState state) {
+    return RegState::NOT_REG_MT_NOT_SEARCHING_OP_EM == state ||
+           RegState::NOT_REG_MT_SEARCHING_OP_EM == state || RegState::REG_DENIED_EM == state ||
+           RegState::UNKNOWN_EM == state;
+}
+
+bool stringEndsWith(std::string const& string, std::string const& end) {
+    if (string.size() >= end.size()) {
+        return std::equal(end.rbegin(), end.rend(), string.rbegin());
+    } else {
+        return false;
+    }
+}
+
+bool isServiceValidForDeviceConfiguration(std::string& serviceName) {
+    if (isSsSsEnabled()) {
+        // Device is configured as SSSS.
+        if (!stringEndsWith(serviceName, RADIO_SERVICE_SLOT1_NAME)) {
+            ALOGI("%s instance is not valid for SSSS device.", serviceName.c_str());
+            return false;
+        }
+    } else if (isDsDsEnabled()) {
+        // Device is configured as DSDS.
+        if (!stringEndsWith(serviceName, RADIO_SERVICE_SLOT1_NAME) &&
+            !stringEndsWith(serviceName, RADIO_SERVICE_SLOT2_NAME)) {
+            ALOGI("%s instance is not valid for DSDS device.", serviceName.c_str());
+            return false;
+        }
+    } else if (isTsTsEnabled()) {
+        // Device is configured as TSTS.
+        if (!stringEndsWith(serviceName, RADIO_SERVICE_SLOT1_NAME) &&
+            !stringEndsWith(serviceName, RADIO_SERVICE_SLOT2_NAME) &&
+            !stringEndsWith(serviceName, RADIO_SERVICE_SLOT3_NAME)) {
+            ALOGI("%s instance is not valid for TSTS device.", serviceName.c_str());
+            return false;
+        }
+    }
+    return true;
+}
+
+/*
+ * Notify that the response message is received.
+ */
+void RadioServiceTest::notify(int receivedSerial) {
+    std::unique_lock<std::mutex> lock(mtx_);
+    if (serial == receivedSerial) {
+        count_++;
+        cv_.notify_one();
+    }
+}
+
+/*
+ * Wait till the response message is notified or till WAIT_TIMEOUT_PERIOD.
+ */
+std::cv_status RadioServiceTest::wait() {
+    std::unique_lock<std::mutex> lock(mtx_);
+    std::cv_status status = std::cv_status::no_timeout;
+    auto now = std::chrono::system_clock::now();
+    while (count_ == 0) {
+        status = cv_.wait_until(lock, now + std::chrono::seconds(WAIT_TIMEOUT_PERIOD));
+        if (status == std::cv_status::timeout) {
+            return status;
+        }
+    }
+    count_--;
+    return status;
+}
+
+/**
+ * Specific features on the Radio HAL rely on Radio HAL Capabilities.
+ * The VTS test related to those features must not run if the related capability is disabled.
+ * Typical usage within VTS:
+ * if (getRadioHalCapabilities()) return;
+ */
+bool RadioServiceTest::getRadioHalCapabilities() {
+    // Get HalDeviceCapabilities from RadioConfig
+    std::shared_ptr<RadioConfigResponse> radioConfigRsp =
+            ndk::SharedRefBase::make<RadioConfigResponse>(*this);
+    std::shared_ptr<RadioConfigIndication> radioConfigInd =
+            ndk::SharedRefBase::make<RadioConfigIndication>(*this);
+    radio_config->setResponseFunctions(radioConfigRsp, radioConfigInd);
+    serial = GetRandomSerialNumber();
+    radio_config->getHalDeviceCapabilities(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    return radioConfigRsp->modemReducedFeatureSet1;
+}
+
+/**
+ * Some VTS tests require the SIM card status to be present before running.
+ * Update the SIM card status, which can be accessed via the extern cardStatus.
+ */
+void RadioServiceTest::updateSimCardStatus() {
+    // Update CardStatus from RadioSim
+    std::shared_ptr<RadioSimResponse> radioSimRsp =
+            ndk::SharedRefBase::make<RadioSimResponse>(*this);
+    std::shared_ptr<RadioSimIndication> radioSimInd =
+            ndk::SharedRefBase::make<RadioSimIndication>(*this);
+    radio_sim->setResponseFunctions(radioSimRsp, radioSimInd);
+    serial = GetRandomSerialNumber();
+    radio_sim->getIccCardStatus(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioSimRsp->rspInfo.type);
+    EXPECT_EQ(serial, radioSimRsp->rspInfo.serial);
+    EXPECT_EQ(RadioError::NONE, radioSimRsp->rspInfo.error);
+}
+
+void RadioServiceTest::updateSimSlotStatus(int physicalSlotId) {
+    // Update SimSlotStatus from RadioConfig
+    std::shared_ptr<RadioConfigResponse> radioConfigRsp =
+            ndk::SharedRefBase::make<RadioConfigResponse>(*this);
+    std::shared_ptr<RadioConfigIndication> radioConfigInd =
+            ndk::SharedRefBase::make<RadioConfigIndication>(*this);
+    radio_config->setResponseFunctions(radioConfigRsp, radioConfigInd);
+    serial = GetRandomSerialNumber();
+    radio_config->getSimSlotsStatus(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioConfigRsp->rspInfo.type);
+    EXPECT_EQ(serial, radioConfigRsp->rspInfo.serial);
+    EXPECT_EQ(RadioError::NONE, radioConfigRsp->rspInfo.error);
+    if (radioConfigRsp->simSlotStatus.size() > physicalSlotId) {
+        slotStatus = radioConfigRsp->simSlotStatus[physicalSlotId];
+    }
+}
diff --git a/radio/aidl/vts/radio_aidl_hal_utils.h b/radio/aidl/vts/radio_aidl_hal_utils.h
new file mode 100644
index 0000000..47976b9
--- /dev/null
+++ b/radio/aidl/vts/radio_aidl_hal_utils.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/radio/RadioError.h>
+#include <aidl/android/hardware/radio/config/IRadioConfig.h>
+#include <aidl/android/hardware/radio/config/SimSlotStatus.h>
+#include <aidl/android/hardware/radio/network/RegState.h>
+#include <aidl/android/hardware/radio/sim/CardStatus.h>
+#include <aidl/android/hardware/radio/sim/IRadioSim.h>
+#include <utils/Log.h>
+#include <vector>
+
+using namespace aidl::android::hardware::radio;
+using aidl::android::hardware::radio::config::SimSlotStatus;
+using aidl::android::hardware::radio::network::RegState;
+using aidl::android::hardware::radio::sim::CardStatus;
+
+extern CardStatus cardStatus;
+extern SimSlotStatus slotStatus;
+extern int serial;
+extern int count_;
+
+/*
+ * MACRO used to skip test case when radio response return error REQUEST_NOT_SUPPORTED
+ * on HAL versions which has deprecated the request interfaces. The MACRO can only be used
+ * AFTER receiving radio response.
+ */
+#define SKIP_TEST_IF_REQUEST_NOT_SUPPORTED_WITH_HAL(__ver__, __radio__, __radioRsp__)      \
+    do {                                                                                   \
+        sp<::android::hardware::radio::V##__ver__::IRadio> __radio =                       \
+                ::android::hardware::radio::V##__ver__::IRadio::castFrom(__radio__);       \
+        if (__radio && __radioRsp__->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED) { \
+            GTEST_SKIP() << "REQUEST_NOT_SUPPORTED";                                       \
+        }                                                                                  \
+    } while (0)
+
+enum CheckFlag {
+    CHECK_DEFAULT = 0,
+    CHECK_GENERAL_ERROR = 1,
+    CHECK_OEM_ERROR = 2,
+    CHECK_OEM_AND_GENERAL_ERROR = 3,
+    CHECK_SAP_ERROR = 4,
+};
+
+static constexpr const char* FEATURE_VOICE_CALL = "android.software.connectionservice";
+
+static constexpr const char* FEATURE_TELEPHONY = "android.hardware.telephony";
+
+static constexpr const char* FEATURE_TELEPHONY_GSM = "android.hardware.telephony.gsm";
+
+static constexpr const char* FEATURE_TELEPHONY_CDMA = "android.hardware.telephony.cdma";
+
+#define MODEM_EMERGENCY_CALL_ESTABLISH_TIME 3
+#define MODEM_EMERGENCY_CALL_DISCONNECT_TIME 3
+#define MODEM_SET_SIM_POWER_DELAY_IN_SECONDS 2
+#define MODEM_SET_SIM_SLOT_MAPPING_DELAY_IN_SECONDS 6
+
+#define RADIO_SERVICE_SLOT1_NAME "slot1"  // HAL instance name for SIM slot 1 or single SIM device
+#define RADIO_SERVICE_SLOT2_NAME "slot2"  // HAL instance name for SIM slot 2 on dual SIM device
+#define RADIO_SERVICE_SLOT3_NAME "slot3"  // HAL instance name for SIM slot 3 on triple SIM device
+
+/*
+ * Generate random serial number for radio test
+ */
+int GetRandomSerialNumber();
+
+/*
+ * Check multiple radio error codes which are possibly returned because of the different
+ * vendor/devices implementations. It allows optional checks for general errors or/and oem errors.
+ */
+::testing::AssertionResult CheckAnyOfErrors(RadioError err, std::vector<RadioError> generalError,
+                                            CheckFlag flag = CHECK_DEFAULT);
+
+/*
+ * Check if device supports feature.
+ */
+bool deviceSupportsFeature(const char* feature);
+
+/*
+ * Check if device is in SsSs (Single SIM Single Standby).
+ */
+bool isSsSsEnabled();
+
+/*
+ * Check if device is in DSDS (Dual SIM Dual Standby).
+ */
+bool isDsDsEnabled();
+
+/*
+ * Check if device is in TSTS (Triple SIM Triple Standby).
+ */
+bool isTsTsEnabled();
+
+/*
+ * Check if voice status is in emergency only.
+ */
+bool isVoiceEmergencyOnly(RegState state);
+
+/*
+ * Check if voice status is in service.
+ */
+bool isVoiceInService(RegState state);
+
+/*
+ * Check if service is valid for device configuration
+ */
+bool isServiceValidForDeviceConfiguration(std::string& serviceName);
+
+/**
+ * RadioServiceTest base class
+ */
+class RadioServiceTest {
+  protected:
+    std::mutex mtx_;
+    std::condition_variable cv_;
+    std::shared_ptr<config::IRadioConfig> radio_config;
+    std::shared_ptr<sim::IRadioSim> radio_sim;
+
+  public:
+    /* Used as a mechanism to inform the test about data/event callback */
+    void notify(int receivedSerial);
+
+    /* Test code calls this function to wait for response */
+    std::cv_status wait();
+
+    /* Get the radio HAL capabilities */
+    bool getRadioHalCapabilities();
+
+    /* Update SIM card status */
+    void updateSimCardStatus();
+
+    /* Update SIM slot status */
+    void updateSimSlotStatus(int physicalSlotId);
+};
diff --git a/radio/aidl/vts/radio_config_indication.cpp b/radio/aidl/vts/radio_config_indication.cpp
new file mode 100644
index 0000000..a84c20b
--- /dev/null
+++ b/radio/aidl/vts/radio_config_indication.cpp
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "radio_config_utils.h"
+
+RadioConfigIndication::RadioConfigIndication(RadioServiceTest& parent) : parent_config(parent) {}
+
+ndk::ScopedAStatus RadioConfigIndication::simSlotsStatusChanged(
+        RadioIndicationType /*type*/, const std::vector<SimSlotStatus>& /*slotStatus*/) {
+    return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_config_response.cpp b/radio/aidl/vts/radio_config_response.cpp
new file mode 100644
index 0000000..7384f87
--- /dev/null
+++ b/radio/aidl/vts/radio_config_response.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "radio_config_utils.h"
+
+RadioConfigResponse::RadioConfigResponse(RadioServiceTest& parent) : parent_config(parent) {}
+
+ndk::ScopedAStatus RadioConfigResponse::getSimSlotsStatusResponse(
+        const RadioResponseInfo& info, const std::vector<SimSlotStatus>& slotStatus) {
+    rspInfo = info;
+    simSlotStatus = slotStatus;
+    parent_config.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioConfigResponse::setSimSlotsMappingResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_config.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioConfigResponse::getPhoneCapabilityResponse(
+        const RadioResponseInfo& info, const PhoneCapability& phoneCapability) {
+    rspInfo = info;
+    phoneCap = phoneCapability;
+    parent_config.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioConfigResponse::setPreferredDataModemResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_config.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioConfigResponse::getNumOfLiveModemsResponse(
+        const RadioResponseInfo& info, const int8_t /* numOfLiveModems */) {
+    rspInfo = info;
+    parent_config.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioConfigResponse::setNumOfLiveModemsResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_config.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioConfigResponse::getHalDeviceCapabilitiesResponse(
+        const RadioResponseInfo& info, bool modemReducedFeatures) {
+    rspInfo = info;
+    modemReducedFeatureSet1 = modemReducedFeatures;
+    parent_config.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_config_test.cpp b/radio/aidl/vts/radio_config_test.cpp
new file mode 100644
index 0000000..258b172
--- /dev/null
+++ b/radio/aidl/vts/radio_config_test.cpp
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+
+#include "radio_config_utils.h"
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
+
+void RadioConfigTest::SetUp() {
+    std::string serviceName = GetParam();
+
+    radio_config = IRadioConfig::fromBinder(
+            ndk::SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+    ASSERT_NE(nullptr, radio_config.get());
+
+    radioRsp_config = ndk::SharedRefBase::make<RadioConfigResponse>(*this);
+    ASSERT_NE(nullptr, radioRsp_config.get());
+
+    count_ = 0;
+
+    radioInd_config = ndk::SharedRefBase::make<RadioConfigIndication>(*this);
+    ASSERT_NE(nullptr, radioInd_config.get());
+
+    radio_config->setResponseFunctions(radioRsp_config, radioInd_config);
+}
+
+void RadioConfigTest::updateSimSlotStatus() {
+    serial = GetRandomSerialNumber();
+    radio_config->getSimSlotsStatus(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_config->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_config->rspInfo.serial);
+    EXPECT_EQ(RadioError::NONE, radioRsp_config->rspInfo.error);
+    // assuming only 1 slot
+    for (const SimSlotStatus& slotStatusResponse : radioRsp_config->simSlotStatus) {
+        slotStatus = slotStatusResponse;
+    }
+}
+
+/*
+ * Test IRadioConfig.getHalDeviceCapabilities() for the response returned.
+ */
+TEST_P(RadioConfigTest, getHalDeviceCapabilities) {
+    serial = GetRandomSerialNumber();
+    ndk::ScopedAStatus res = radio_config->getHalDeviceCapabilities(serial);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    ALOGI("getHalDeviceCapabilities, rspInfo.error = %s\n",
+          toString(radioRsp_config->rspInfo.error).c_str());
+}
+
+/*
+ * Test IRadioConfig.getSimSlotsStatus() for the response returned.
+ */
+TEST_P(RadioConfigTest, getSimSlotsStatus) {
+    serial = GetRandomSerialNumber();
+    ndk::ScopedAStatus res = radio_config->getSimSlotsStatus(serial);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    ALOGI("getSimSlotsStatus, rspInfo.error = %s\n",
+          toString(radioRsp_config->rspInfo.error).c_str());
+}
+
+/*
+ * Test IRadioConfig.getPhoneCapability() for the response returned.
+ */
+TEST_P(RadioConfigTest, getPhoneCapability) {
+    serial = GetRandomSerialNumber();
+    ndk::ScopedAStatus res = radio_config->getPhoneCapability(serial);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_config->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_config->rspInfo.serial);
+    ALOGI("getPhoneCapability, rspInfo.error = %s\n",
+          toString(radioRsp_config->rspInfo.error).c_str());
+
+    ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp_config->rspInfo.error,
+            {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::INTERNAL_ERR}));
+
+    if (radioRsp_config->rspInfo.error == RadioError ::NONE) {
+        // maxActiveData should be greater than or equal to maxActiveInternetData.
+        EXPECT_GE(radioRsp_config->phoneCap.maxActiveData,
+                  radioRsp_config->phoneCap.maxActiveInternetData);
+        // maxActiveData and maxActiveInternetData should be 0 or positive numbers.
+        EXPECT_GE(radioRsp_config->phoneCap.maxActiveInternetData, 0);
+    }
+}
+
+/*
+ * Test IRadioConfig.setPreferredDataModem() for the response returned.
+ */
+TEST_P(RadioConfigTest, setPreferredDataModem) {
+    serial = GetRandomSerialNumber();
+    ndk::ScopedAStatus res = radio_config->getPhoneCapability(serial);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_config->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_config->rspInfo.serial);
+    ALOGI("getPhoneCapability, rspInfo.error = %s\n",
+          toString(radioRsp_config->rspInfo.error).c_str());
+
+    ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp_config->rspInfo.error,
+            {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::INTERNAL_ERR}));
+
+    if (radioRsp_config->rspInfo.error != RadioError ::NONE) {
+        return;
+    }
+
+    if (radioRsp_config->phoneCap.logicalModemIds.size() == 0) {
+        return;
+    }
+
+    // We get phoneCapability. Send setPreferredDataModem command
+    serial = GetRandomSerialNumber();
+    uint8_t modemId = radioRsp_config->phoneCap.logicalModemIds[0];
+    res = radio_config->setPreferredDataModem(serial, modemId);
+
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_config->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_config->rspInfo.serial);
+    ALOGI("setPreferredDataModem, rspInfo.error = %s\n",
+          toString(radioRsp_config->rspInfo.error).c_str());
+
+    ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp_config->rspInfo.error,
+            {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::INTERNAL_ERR}));
+}
+
+/*
+ * Test IRadioConfig.setPreferredDataModem() with invalid arguments.
+ */
+TEST_P(RadioConfigTest, setPreferredDataModem_invalidArgument) {
+    serial = GetRandomSerialNumber();
+    uint8_t modemId = -1;
+    ndk::ScopedAStatus res = radio_config->setPreferredDataModem(serial, modemId);
+
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_config->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_config->rspInfo.serial);
+    ALOGI("setPreferredDataModem, rspInfo.error = %s\n",
+          toString(radioRsp_config->rspInfo.error).c_str());
+
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_config->rspInfo.error,
+                                 {RadioError::INVALID_ARGUMENTS, RadioError::RADIO_NOT_AVAILABLE,
+                                  RadioError::INTERNAL_ERR}));
+}
+
+/*
+ * Test IRadioConfig.setSimSlotsMapping() for the response returned.
+ */
+TEST_P(RadioConfigTest, setSimSlotsMapping) {
+    // get slot status and set SIM slots mapping based on the result.
+    updateSimSlotStatus();
+    if (radioRsp_config->rspInfo.error == RadioError::NONE) {
+        SlotPortMapping slotPortMapping;
+        // put invalid value at first and adjust by slotStatusResponse.
+        slotPortMapping.physicalSlotId = -1;
+        slotPortMapping.portId = -1;
+        std::vector<SlotPortMapping> slotPortMappingList = {slotPortMapping};
+        if (isDsDsEnabled()) {
+            slotPortMappingList.push_back(slotPortMapping);
+        } else if (isTsTsEnabled()) {
+            slotPortMappingList.push_back(slotPortMapping);
+            slotPortMappingList.push_back(slotPortMapping);
+        }
+        for (size_t i = 0; i < radioRsp_config->simSlotStatus.size(); i++) {
+            ASSERT_TRUE(radioRsp_config->simSlotStatus[i].portInfo.size() > 0);
+            for (size_t j = 0; j < radioRsp_config->simSlotStatus[i].portInfo.size(); j++) {
+                if (radioRsp_config->simSlotStatus[i].portInfo[j].portActive) {
+                    int32_t logicalSlotId =
+                            radioRsp_config->simSlotStatus[i].portInfo[j].logicalSlotId;
+                    // logicalSlotId should be 0 or positive numbers if the port
+                    // is active.
+                    EXPECT_GE(logicalSlotId, 0);
+                    // logicalSlotId should be less than the maximum number of
+                    // supported SIM slots.
+                    EXPECT_LT(logicalSlotId, slotPortMappingList.size());
+                    if (logicalSlotId >= 0 && logicalSlotId < slotPortMappingList.size()) {
+                        slotPortMappingList[logicalSlotId].physicalSlotId = i;
+                        slotPortMappingList[logicalSlotId].portId = j;
+                    }
+                }
+            }
+        }
+
+        // set SIM slots mapping
+        for (size_t i = 0; i < slotPortMappingList.size(); i++) {
+            // physicalSlotId and portId should be 0 or positive numbers for the
+            // input of setSimSlotsMapping.
+            EXPECT_GE(slotPortMappingList[i].physicalSlotId, 0);
+            EXPECT_GE(slotPortMappingList[i].portId, 0);
+        }
+        serial = GetRandomSerialNumber();
+        ndk::ScopedAStatus res = radio_config->setSimSlotsMapping(serial, slotPortMappingList);
+        ASSERT_OK(res);
+        EXPECT_EQ(std::cv_status::no_timeout, wait());
+        EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_config->rspInfo.type);
+        EXPECT_EQ(serial, radioRsp_config->rspInfo.serial);
+        ALOGI("setSimSlotsMapping, rspInfo.error = %s\n",
+              toString(radioRsp_config->rspInfo.error).c_str());
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_config->rspInfo.error, {RadioError::NONE}));
+
+        // Give some time for modem to fully switch SIM configuration
+        sleep(MODEM_SET_SIM_SLOT_MAPPING_DELAY_IN_SECONDS);
+    }
+}
+
+/*
+ * Test IRadioConfig.getSimSlotStatus() for the response returned.
+ */
+
+TEST_P(RadioConfigTest, checkPortInfoExistsAndPortActive) {
+    serial = GetRandomSerialNumber();
+    ndk::ScopedAStatus res = radio_config->getSimSlotsStatus(serial);
+    ASSERT_OK(res);
+    ALOGI("getSimSlotsStatus, rspInfo.error = %s\n",
+          toString(radioRsp_config->rspInfo.error).c_str());
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_config->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_config->rspInfo.serial);
+    if (radioRsp_config->rspInfo.error == RadioError::NONE) {
+        uint8_t simCount = 0;
+        // check if cardState is present, portInfo size should be more than 0
+        for (const SimSlotStatus& slotStatusResponse : radioRsp_config->simSlotStatus) {
+            if (slotStatusResponse.cardState == CardStatus::STATE_PRESENT) {
+                ASSERT_TRUE(slotStatusResponse.portInfo.size() > 0);
+                for (const SimPortInfo& simPortInfo : slotStatusResponse.portInfo) {
+                    if (simPortInfo.portActive) {
+                        simCount++;
+                    }
+                }
+            }
+        }
+        if (isSsSsEnabled()) {
+            EXPECT_EQ(1, simCount);
+        } else if (isDsDsEnabled()) {
+            EXPECT_EQ(2, simCount);
+        } else if (isTsTsEnabled()) {
+            EXPECT_EQ(3, simCount);
+        }
+    }
+}
diff --git a/radio/aidl/vts/radio_config_utils.h b/radio/aidl/vts/radio_config_utils.h
new file mode 100644
index 0000000..3db430d
--- /dev/null
+++ b/radio/aidl/vts/radio_config_utils.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/radio/config/BnRadioConfigIndication.h>
+#include <aidl/android/hardware/radio/config/BnRadioConfigResponse.h>
+#include <aidl/android/hardware/radio/config/IRadioConfig.h>
+
+#include "radio_aidl_hal_utils.h"
+
+using namespace aidl::android::hardware::radio::config;
+
+class RadioConfigTest;
+
+/* Callback class for radio config response */
+class RadioConfigResponse : public BnRadioConfigResponse {
+  protected:
+    RadioServiceTest& parent_config;
+
+  public:
+    RadioConfigResponse(RadioServiceTest& parent_config);
+    virtual ~RadioConfigResponse() = default;
+
+    RadioResponseInfo rspInfo;
+    PhoneCapability phoneCap;
+    bool modemReducedFeatureSet1;
+    std::vector<SimSlotStatus> simSlotStatus;
+
+    virtual ndk::ScopedAStatus getSimSlotsStatusResponse(
+            const RadioResponseInfo& info, const std::vector<SimSlotStatus>& slotStatus) override;
+
+    virtual ndk::ScopedAStatus setSimSlotsMappingResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus getPhoneCapabilityResponse(
+            const RadioResponseInfo& info, const PhoneCapability& phoneCapability) override;
+
+    virtual ndk::ScopedAStatus setPreferredDataModemResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus getNumOfLiveModemsResponse(const RadioResponseInfo& info,
+                                                          const int8_t numOfLiveModems) override;
+
+    virtual ndk::ScopedAStatus setNumOfLiveModemsResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus getHalDeviceCapabilitiesResponse(
+            const RadioResponseInfo& info, bool modemReducedFeatureSet1) override;
+};
+
+/* Callback class for radio config indication */
+class RadioConfigIndication : public BnRadioConfigIndication {
+  protected:
+    RadioServiceTest& parent_config;
+
+  public:
+    RadioConfigIndication(RadioServiceTest& parent_config);
+    virtual ~RadioConfigIndication() = default;
+
+    virtual ndk::ScopedAStatus simSlotsStatusChanged(
+            RadioIndicationType type, const std::vector<SimSlotStatus>& slotStatus) override;
+};
+
+// The main test class for Radio AIDL Config.
+class RadioConfigTest : public ::testing::TestWithParam<std::string>, public RadioServiceTest {
+  public:
+    virtual void SetUp() override;
+    ndk::ScopedAStatus updateSimCardStatus();
+    /* Override updateSimSlotStatus in RadioServiceTest to not call setResponseFunctions */
+    void updateSimSlotStatus();
+
+    /* radio config service handle in RadioServiceTest */
+    /* radio config response handle */
+    std::shared_ptr<RadioConfigResponse> radioRsp_config;
+    /* radio config indication handle */
+    std::shared_ptr<RadioConfigIndication> radioInd_config;
+};
diff --git a/radio/aidl/vts/radio_data_indication.cpp b/radio/aidl/vts/radio_data_indication.cpp
new file mode 100644
index 0000000..61e079e
--- /dev/null
+++ b/radio/aidl/vts/radio_data_indication.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "radio_data_utils.h"
+
+RadioDataIndication::RadioDataIndication(RadioServiceTest& parent) : parent_data(parent) {}
+
+ndk::ScopedAStatus RadioDataIndication::dataCallListChanged(
+        RadioIndicationType /*type*/, const std::vector<SetupDataCallResult>& /*dcList*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataIndication::keepaliveStatus(RadioIndicationType /*type*/,
+                                                        const KeepaliveStatus& /*status*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataIndication::pcoData(RadioIndicationType /*type*/,
+                                                const PcoDataInfo& /*pco*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataIndication::unthrottleApn(RadioIndicationType /*type*/,
+                                                      const DataProfileInfo& /*dataProfileInfo*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataIndication::slicingConfigChanged(
+        RadioIndicationType /*type*/, const SlicingConfig& /*slicingConfig*/) {
+    return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_data_response.cpp b/radio/aidl/vts/radio_data_response.cpp
new file mode 100644
index 0000000..8d51760
--- /dev/null
+++ b/radio/aidl/vts/radio_data_response.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "radio_data_utils.h"
+
+RadioDataResponse::RadioDataResponse(RadioServiceTest& parent) : parent_data(parent) {}
+
+ndk::ScopedAStatus RadioDataResponse::acknowledgeRequest(int32_t /*serial*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::allocatePduSessionIdResponse(const RadioResponseInfo& info,
+                                                                   int32_t id) {
+    rspInfo = info;
+    allocatedPduSessionId = id;
+    parent_data.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::cancelHandoverResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_data.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::deactivateDataCallResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_data.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::getDataCallListResponse(
+        const RadioResponseInfo& info, const std::vector<SetupDataCallResult>& /*dcResponse*/) {
+    rspInfo = info;
+    parent_data.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::getSlicingConfigResponse(
+        const RadioResponseInfo& info, const SlicingConfig& /*slicingConfig*/) {
+    rspInfo = info;
+    parent_data.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::releasePduSessionIdResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_data.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::setDataAllowedResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_data.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::setDataProfileResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_data.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::setDataThrottlingResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_data.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::setInitialAttachApnResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_data.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::setupDataCallResponse(const RadioResponseInfo& info,
+                                                            const SetupDataCallResult& dcResponse) {
+    rspInfo = info;
+    setupDataCallResult = dcResponse;
+    parent_data.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::startHandoverResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_data.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::startKeepaliveResponse(const RadioResponseInfo& info,
+                                                             const KeepaliveStatus& /*status*/) {
+    rspInfo = info;
+    parent_data.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioDataResponse::stopKeepaliveResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_data.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_data_test.cpp b/radio/aidl/vts/radio_data_test.cpp
new file mode 100644
index 0000000..f38a958
--- /dev/null
+++ b/radio/aidl/vts/radio_data_test.cpp
@@ -0,0 +1,588 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aidl/android/hardware/radio/RadioAccessFamily.h>
+#include <aidl/android/hardware/radio/config/IRadioConfig.h>
+#include <aidl/android/hardware/radio/data/ApnTypes.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+
+#include "radio_data_utils.h"
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
+
+void RadioDataTest::SetUp() {
+    std::string serviceName = GetParam();
+
+    if (!isServiceValidForDeviceConfiguration(serviceName)) {
+        ALOGI("Skipped the test due to device configuration.");
+        GTEST_SKIP();
+    }
+
+    radio_data = IRadioData::fromBinder(
+            ndk::SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+    ASSERT_NE(nullptr, radio_data.get());
+
+    radioRsp_data = ndk::SharedRefBase::make<RadioDataResponse>(*this);
+    ASSERT_NE(nullptr, radioRsp_data.get());
+
+    count_ = 0;
+
+    radioInd_data = ndk::SharedRefBase::make<RadioDataIndication>(*this);
+    ASSERT_NE(nullptr, radioInd_data.get());
+
+    radio_data->setResponseFunctions(radioRsp_data, radioInd_data);
+
+    // Assert IRadioSim exists and SIM is present before testing
+    radio_sim = sim::IRadioSim::fromBinder(ndk::SpAIBinder(
+            AServiceManager_waitForService("android.hardware.radio.sim.IRadioSim/slot1")));
+    ASSERT_NE(nullptr, radio_sim.get());
+    updateSimCardStatus();
+    EXPECT_EQ(CardStatus::STATE_PRESENT, cardStatus.cardState);
+
+    // Assert IRadioConfig exists before testing
+    radio_config = config::IRadioConfig::fromBinder(ndk::SpAIBinder(
+            AServiceManager_waitForService("android.hardware.radio.config.IRadioConfig/default")));
+    ASSERT_NE(nullptr, radio_config.get());
+}
+
+ndk::ScopedAStatus RadioDataTest::getDataCallList() {
+    serial = GetRandomSerialNumber();
+    radio_data->getDataCallList(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    return ndk::ScopedAStatus::ok();
+}
+
+/*
+ * Test IRadioData.setupDataCall() for the response returned.
+ */
+TEST_P(RadioDataTest, setupDataCall) {
+    serial = GetRandomSerialNumber();
+
+    AccessNetwork accessNetwork = AccessNetwork::EUTRAN;
+
+    DataProfileInfo dataProfileInfo;
+    memset(&dataProfileInfo, 0, sizeof(dataProfileInfo));
+    dataProfileInfo.profileId = DataProfileInfo::ID_DEFAULT;
+    dataProfileInfo.apn = std::string("internet");
+    dataProfileInfo.protocol = PdpProtocolType::IP;
+    dataProfileInfo.roamingProtocol = PdpProtocolType::IP;
+    dataProfileInfo.authType = ApnAuthType::NO_PAP_NO_CHAP;
+    dataProfileInfo.user = std::string("username");
+    dataProfileInfo.password = std::string("password");
+    dataProfileInfo.type = DataProfileInfo::TYPE_3GPP;
+    dataProfileInfo.maxConnsTime = 300;
+    dataProfileInfo.maxConns = 20;
+    dataProfileInfo.waitTime = 0;
+    dataProfileInfo.enabled = true;
+    dataProfileInfo.supportedApnTypesBitmap =
+            static_cast<int32_t>(ApnTypes::IMS) | static_cast<int32_t>(ApnTypes::IA);
+    dataProfileInfo.bearerBitmap = static_cast<int32_t>(RadioAccessFamily::GPRS) |
+                                   static_cast<int32_t>(RadioAccessFamily::EDGE) |
+                                   static_cast<int32_t>(RadioAccessFamily::UMTS) |
+                                   static_cast<int32_t>(RadioAccessFamily::HSDPA) |
+                                   static_cast<int32_t>(RadioAccessFamily::HSUPA) |
+                                   static_cast<int32_t>(RadioAccessFamily::HSPA) |
+                                   static_cast<int32_t>(RadioAccessFamily::EHRPD) |
+                                   static_cast<int32_t>(RadioAccessFamily::LTE) |
+                                   static_cast<int32_t>(RadioAccessFamily::HSPAP) |
+                                   static_cast<int32_t>(RadioAccessFamily::IWLAN);
+    dataProfileInfo.mtuV4 = 0;
+    dataProfileInfo.mtuV6 = 0;
+    dataProfileInfo.preferred = true;
+    dataProfileInfo.persistent = false;
+
+    bool roamingAllowed = false;
+
+    std::vector<LinkAddress> addresses = {};
+    std::vector<std::string> dnses = {};
+
+    DataRequestReason reason = DataRequestReason::NORMAL;
+    SliceInfo sliceInfo;
+    bool matchAllRuleAllowed = true;
+
+    ndk::ScopedAStatus res =
+            radio_data->setupDataCall(serial, accessNetwork, dataProfileInfo, roamingAllowed,
+                                      reason, addresses, dnses, -1, sliceInfo, matchAllRuleAllowed);
+    ASSERT_OK(res);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_data->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_data->rspInfo.serial);
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+                                     {RadioError::SIM_ABSENT, RadioError::RADIO_NOT_AVAILABLE,
+                                      RadioError::OP_NOT_ALLOWED_BEFORE_REG_TO_NW}));
+    } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+                                     {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
+                                      RadioError::OP_NOT_ALLOWED_BEFORE_REG_TO_NW}));
+    }
+}
+
+/*
+ * Test IRadioData.setupDataCall() with osAppId for the response returned.
+ */
+TEST_P(RadioDataTest, setupDataCall_osAppId) {
+    serial = GetRandomSerialNumber();
+
+    AccessNetwork accessNetwork = AccessNetwork::EUTRAN;
+
+    TrafficDescriptor trafficDescriptor;
+    OsAppId osAppId;
+    std::string osAppIdString("osAppId");
+    std::vector<unsigned char> osAppIdVec(osAppIdString.begin(), osAppIdString.end());
+    osAppId.osAppId = osAppIdVec;
+    trafficDescriptor.osAppId = osAppId;
+
+    DataProfileInfo dataProfileInfo;
+    memset(&dataProfileInfo, 0, sizeof(dataProfileInfo));
+    dataProfileInfo.profileId = DataProfileInfo::ID_DEFAULT;
+    dataProfileInfo.apn = std::string("internet");
+    dataProfileInfo.protocol = PdpProtocolType::IP;
+    dataProfileInfo.roamingProtocol = PdpProtocolType::IP;
+    dataProfileInfo.authType = ApnAuthType::NO_PAP_NO_CHAP;
+    dataProfileInfo.user = std::string("username");
+    dataProfileInfo.password = std::string("password");
+    dataProfileInfo.type = DataProfileInfo::TYPE_3GPP;
+    dataProfileInfo.maxConnsTime = 300;
+    dataProfileInfo.maxConns = 20;
+    dataProfileInfo.waitTime = 0;
+    dataProfileInfo.enabled = true;
+    dataProfileInfo.supportedApnTypesBitmap =
+            static_cast<int32_t>(ApnTypes::IMS) | static_cast<int32_t>(ApnTypes::IA);
+    dataProfileInfo.bearerBitmap = static_cast<int32_t>(RadioAccessFamily::GPRS) |
+                                   static_cast<int32_t>(RadioAccessFamily::EDGE) |
+                                   static_cast<int32_t>(RadioAccessFamily::UMTS) |
+                                   static_cast<int32_t>(RadioAccessFamily::HSDPA) |
+                                   static_cast<int32_t>(RadioAccessFamily::HSUPA) |
+                                   static_cast<int32_t>(RadioAccessFamily::HSPA) |
+                                   static_cast<int32_t>(RadioAccessFamily::EHRPD) |
+                                   static_cast<int32_t>(RadioAccessFamily::LTE) |
+                                   static_cast<int32_t>(RadioAccessFamily::HSPAP) |
+                                   static_cast<int32_t>(RadioAccessFamily::IWLAN);
+    dataProfileInfo.mtuV4 = 0;
+    dataProfileInfo.mtuV6 = 0;
+    dataProfileInfo.preferred = true;
+    dataProfileInfo.persistent = false;
+    dataProfileInfo.trafficDescriptor = trafficDescriptor;
+
+    bool roamingAllowed = false;
+
+    std::vector<LinkAddress> addresses = {};
+    std::vector<std::string> dnses = {};
+
+    DataRequestReason reason = DataRequestReason::NORMAL;
+    SliceInfo sliceInfo;
+    bool matchAllRuleAllowed = true;
+
+    ndk::ScopedAStatus res =
+            radio_data->setupDataCall(serial, accessNetwork, dataProfileInfo, roamingAllowed,
+                                      reason, addresses, dnses, -1, sliceInfo, matchAllRuleAllowed);
+    ASSERT_OK(res);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_data->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_data->rspInfo.serial);
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+                                     {RadioError::SIM_ABSENT, RadioError::RADIO_NOT_AVAILABLE,
+                                      RadioError::OP_NOT_ALLOWED_BEFORE_REG_TO_NW}));
+    } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+                                     {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
+                                      RadioError::OP_NOT_ALLOWED_BEFORE_REG_TO_NW}));
+        if (radioRsp_data->setupDataCallResult.trafficDescriptors.size() <= 0) {
+            return;
+        }
+        EXPECT_EQ(trafficDescriptor.osAppId.value().osAppId,
+                  radioRsp_data->setupDataCallResult.trafficDescriptors[0].osAppId.value().osAppId);
+    }
+}
+
+/*
+ * Test IRadioData.getSlicingConfig() for the response returned.
+ */
+TEST_P(RadioDataTest, getSlicingConfig) {
+    serial = GetRandomSerialNumber();
+    radio_data->getSlicingConfig(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_data->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_data->rspInfo.serial);
+    if (getRadioHalCapabilities()) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+                                     {RadioError::REQUEST_NOT_SUPPORTED}));
+    } else {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+                                     {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
+                                      RadioError::INTERNAL_ERR, RadioError::MODEM_ERR}));
+    }
+}
+
+/*
+ * Test IRadioData.setDataThrottling() for the response returned.
+ */
+TEST_P(RadioDataTest, setDataThrottling) {
+    serial = GetRandomSerialNumber();
+
+    ndk::ScopedAStatus res = radio_data->setDataThrottling(
+            serial, DataThrottlingAction::THROTTLE_SECONDARY_CARRIER, 60000);
+    ASSERT_OK(res);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_data->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_data->rspInfo.serial);
+    if (getRadioHalCapabilities()) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+                                     {RadioError::REQUEST_NOT_SUPPORTED, RadioError::NONE}));
+    } else {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+                                     {RadioError::RADIO_NOT_AVAILABLE, RadioError::MODEM_ERR,
+                                      RadioError::NONE, RadioError::INVALID_ARGUMENTS}));
+    }
+
+    sleep(1);
+    serial = GetRandomSerialNumber();
+
+    res = radio_data->setDataThrottling(serial, DataThrottlingAction::THROTTLE_ANCHOR_CARRIER,
+                                        60000);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_data->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_data->rspInfo.serial);
+    if (getRadioHalCapabilities()) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+                                     {RadioError::REQUEST_NOT_SUPPORTED, RadioError::NONE}));
+    } else {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+                                     {RadioError::RADIO_NOT_AVAILABLE, RadioError::MODEM_ERR,
+                                      RadioError::NONE, RadioError::INVALID_ARGUMENTS}));
+    }
+
+    sleep(1);
+    serial = GetRandomSerialNumber();
+
+    res = radio_data->setDataThrottling(serial, DataThrottlingAction::HOLD, 60000);
+    ASSERT_OK(res);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_data->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_data->rspInfo.serial);
+    if (getRadioHalCapabilities()) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+                                     {RadioError::REQUEST_NOT_SUPPORTED, RadioError::NONE}));
+    } else {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+                                     {RadioError::RADIO_NOT_AVAILABLE, RadioError::MODEM_ERR,
+                                      RadioError::NONE, RadioError::INVALID_ARGUMENTS}));
+    }
+
+    sleep(1);
+    serial = GetRandomSerialNumber();
+
+    res = radio_data->setDataThrottling(serial, DataThrottlingAction::NO_DATA_THROTTLING, 60000);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_data->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_data->rspInfo.serial);
+    if (getRadioHalCapabilities()) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+                                     {RadioError::REQUEST_NOT_SUPPORTED, RadioError::NONE}));
+    } else {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+                                     {RadioError::RADIO_NOT_AVAILABLE, RadioError::MODEM_ERR,
+                                      RadioError::NONE, RadioError::INVALID_ARGUMENTS}));
+    }
+
+    sleep(1);
+}
+
+/*
+ * Test IRadioData.setInitialAttachApn() for the response returned.
+ */
+TEST_P(RadioDataTest, setInitialAttachApn) {
+    serial = GetRandomSerialNumber();
+
+    // Create a dataProfileInfo
+    DataProfileInfo dataProfileInfo;
+    memset(&dataProfileInfo, 0, sizeof(dataProfileInfo));
+    dataProfileInfo.profileId = DataProfileInfo::ID_DEFAULT;
+    dataProfileInfo.apn = std::string("internet");
+    dataProfileInfo.protocol = PdpProtocolType::IPV4V6;
+    dataProfileInfo.roamingProtocol = PdpProtocolType::IPV4V6;
+    dataProfileInfo.authType = ApnAuthType::NO_PAP_NO_CHAP;
+    dataProfileInfo.user = std::string("username");
+    dataProfileInfo.password = std::string("password");
+    dataProfileInfo.type = DataProfileInfo::TYPE_3GPP;
+    dataProfileInfo.maxConnsTime = 300;
+    dataProfileInfo.maxConns = 20;
+    dataProfileInfo.waitTime = 0;
+    dataProfileInfo.enabled = true;
+    dataProfileInfo.supportedApnTypesBitmap = 320;
+    dataProfileInfo.bearerBitmap = 161543;
+    dataProfileInfo.mtuV4 = 0;
+    dataProfileInfo.mtuV6 = 0;
+    dataProfileInfo.preferred = true;
+    dataProfileInfo.persistent = false;
+
+    radio_data->setInitialAttachApn(serial, dataProfileInfo);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_data->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_data->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+                                     {RadioError::SIM_ABSENT, RadioError::RADIO_NOT_AVAILABLE}));
+    } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+                                     {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE}));
+    }
+}
+
+/*
+ * Test IRadioData.setDataProfile() for the response returned.
+ */
+TEST_P(RadioDataTest, setDataProfile) {
+    serial = GetRandomSerialNumber();
+
+    // Create a dataProfileInfo
+    DataProfileInfo dataProfileInfo;
+    memset(&dataProfileInfo, 0, sizeof(dataProfileInfo));
+    dataProfileInfo.profileId = DataProfileInfo::ID_DEFAULT;
+    dataProfileInfo.apn = std::string("internet");
+    dataProfileInfo.protocol = PdpProtocolType::IPV4V6;
+    dataProfileInfo.roamingProtocol = PdpProtocolType::IPV4V6;
+    dataProfileInfo.authType = ApnAuthType::NO_PAP_NO_CHAP;
+    dataProfileInfo.user = std::string("username");
+    dataProfileInfo.password = std::string("password");
+    dataProfileInfo.type = DataProfileInfo::TYPE_3GPP;
+    dataProfileInfo.maxConnsTime = 300;
+    dataProfileInfo.maxConns = 20;
+    dataProfileInfo.waitTime = 0;
+    dataProfileInfo.enabled = true;
+    dataProfileInfo.supportedApnTypesBitmap = 320;
+    dataProfileInfo.bearerBitmap = 161543;
+    dataProfileInfo.mtuV4 = 0;
+    dataProfileInfo.mtuV6 = 0;
+    dataProfileInfo.preferred = true;
+    dataProfileInfo.persistent = true;
+
+    // Create a dataProfileInfoList
+    std::vector<DataProfileInfo> dataProfileInfoList = {dataProfileInfo};
+
+    radio_data->setDataProfile(serial, dataProfileInfoList);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_data->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_data->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+                                     {RadioError::SIM_ABSENT, RadioError::RADIO_NOT_AVAILABLE}));
+    } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+                                     {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE}));
+    }
+}
+
+/*
+ * Test IRadioData.deactivateDataCall() for the response returned.
+ */
+TEST_P(RadioDataTest, deactivateDataCall) {
+    serial = GetRandomSerialNumber();
+    int cid = 1;
+    DataRequestReason reason = DataRequestReason::NORMAL;
+
+    ndk::ScopedAStatus res = radio_data->deactivateDataCall(serial, cid, reason);
+    ASSERT_OK(res);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_data->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_data->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(
+                CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+                                 {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
+                                  RadioError::INVALID_CALL_ID, RadioError::INVALID_STATE,
+                                  RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED,
+                                  RadioError::CANCELLED, RadioError::SIM_ABSENT}));
+    } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_data->rspInfo.error,
+                {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::INVALID_CALL_ID,
+                 RadioError::INVALID_STATE, RadioError::INVALID_ARGUMENTS,
+                 RadioError::REQUEST_NOT_SUPPORTED, RadioError::CANCELLED}));
+    }
+}
+
+/*
+ * Test IRadioData.startKeepalive() for the response returned.
+ */
+TEST_P(RadioDataTest, startKeepalive) {
+    std::vector<KeepaliveRequest> requests = {
+            {
+                    // Invalid IPv4 source address
+                    KeepaliveRequest::TYPE_NATT_IPV4,
+                    {192, 168, 0 /*, 100*/},
+                    1234,
+                    {8, 8, 4, 4},
+                    4500,
+                    20000,
+                    0xBAD,
+            },
+            {
+                    // Invalid IPv4 destination address
+                    KeepaliveRequest::TYPE_NATT_IPV4,
+                    {192, 168, 0, 100},
+                    1234,
+                    {8, 8, 4, 4, 1, 2, 3, 4},
+                    4500,
+                    20000,
+                    0xBAD,
+            },
+            {
+                    // Invalid Keepalive Type
+                    -1,
+                    {192, 168, 0, 100},
+                    1234,
+                    {8, 8, 4, 4},
+                    4500,
+                    20000,
+                    0xBAD,
+            },
+            {
+                    // Invalid IPv6 source address
+                    KeepaliveRequest::TYPE_NATT_IPV6,
+                    {0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE,
+                     0xED, 0xBE, 0xEF, 0xBD},
+                    1234,
+                    {0x20, 0x01, 0x48, 0x60, 0x48, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                     0x00, 0x88, 0x44},
+                    4500,
+                    20000,
+                    0xBAD,
+            },
+            {
+                    // Invalid IPv6 destination address
+                    KeepaliveRequest::TYPE_NATT_IPV6,
+                    {0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE,
+                     0xED, 0xBE, 0xEF},
+                    1234,
+                    {0x20, 0x01, 0x48, 0x60, 0x48, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                     0x00, 0x88,
+                     /*0x44*/},
+                    4500,
+                    20000,
+                    0xBAD,
+            },
+            {
+                    // Invalid Context ID (cid), this should survive the initial
+                    // range checking and fail in the modem data layer
+                    KeepaliveRequest::TYPE_NATT_IPV4,
+                    {192, 168, 0, 100},
+                    1234,
+                    {8, 8, 4, 4},
+                    4500,
+                    20000,
+                    0xBAD,
+            },
+            {
+                    // Invalid Context ID (cid), this should survive the initial
+                    // range checking and fail in the modem data layer
+                    KeepaliveRequest::TYPE_NATT_IPV6,
+                    {0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE,
+                     0xED, 0xBE, 0xEF},
+                    1234,
+                    {0x20, 0x01, 0x48, 0x60, 0x48, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                     0x00, 0x88, 0x44},
+                    4500,
+                    20000,
+                    0xBAD,
+            }};
+
+    for (auto req = requests.begin(); req != requests.end(); req++) {
+        serial = GetRandomSerialNumber();
+        radio_data->startKeepalive(serial, *req);
+        EXPECT_EQ(std::cv_status::no_timeout, wait());
+        EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_data->rspInfo.type);
+        EXPECT_EQ(serial, radioRsp_data->rspInfo.serial);
+
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_data->rspInfo.error,
+                {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::INVALID_ARGUMENTS,
+                 RadioError::REQUEST_NOT_SUPPORTED}));
+    }
+}
+
+/*
+ * Test IRadioData.stopKeepalive() for the response returned.
+ */
+TEST_P(RadioDataTest, stopKeepalive) {
+    serial = GetRandomSerialNumber();
+
+    radio_data->stopKeepalive(serial, 0xBAD);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_data->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_data->rspInfo.serial);
+
+    ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp_data->rspInfo.error,
+                             {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
+                              RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+}
+
+/*
+ * Test IRadioData.getDataCallList() for the response returned.
+ */
+TEST_P(RadioDataTest, getDataCallList) {
+    LOG(DEBUG) << "getDataCallList";
+    serial = GetRandomSerialNumber();
+
+    radio_data->getDataCallList(serial);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_data->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_data->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_data->rspInfo.error,
+                {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::SIM_ABSENT}));
+    }
+    LOG(DEBUG) << "getDataCallList finished";
+}
+
+/*
+ * Test IRadioData.setDataAllowed() for the response returned.
+ */
+TEST_P(RadioDataTest, setDataAllowed) {
+    LOG(DEBUG) << "setDataAllowed";
+    serial = GetRandomSerialNumber();
+    bool allow = true;
+
+    radio_data->setDataAllowed(serial, allow);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_data->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_data->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        EXPECT_EQ(RadioError::NONE, radioRsp_data->rspInfo.error);
+    }
+    LOG(DEBUG) << "setDataAllowed finished";
+}
diff --git a/radio/aidl/vts/radio_data_utils.h b/radio/aidl/vts/radio_data_utils.h
new file mode 100644
index 0000000..fb91ef6
--- /dev/null
+++ b/radio/aidl/vts/radio_data_utils.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/radio/data/BnRadioDataIndication.h>
+#include <aidl/android/hardware/radio/data/BnRadioDataResponse.h>
+#include <aidl/android/hardware/radio/data/IRadioData.h>
+
+#include "radio_aidl_hal_utils.h"
+
+using namespace aidl::android::hardware::radio::data;
+
+class RadioDataTest;
+
+/* Callback class for radio data response */
+class RadioDataResponse : public BnRadioDataResponse {
+  protected:
+    RadioServiceTest& parent_data;
+
+  public:
+    RadioDataResponse(RadioServiceTest& parent_data);
+    virtual ~RadioDataResponse() = default;
+
+    RadioResponseInfo rspInfo;
+    int32_t allocatedPduSessionId;
+    SetupDataCallResult setupDataCallResult;
+
+    virtual ndk::ScopedAStatus acknowledgeRequest(int32_t serial) override;
+
+    virtual ndk::ScopedAStatus allocatePduSessionIdResponse(const RadioResponseInfo& info,
+                                                            int32_t id) override;
+
+    virtual ndk::ScopedAStatus cancelHandoverResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus deactivateDataCallResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus getDataCallListResponse(
+            const RadioResponseInfo& info,
+            const std::vector<SetupDataCallResult>& dcResponse) override;
+
+    virtual ndk::ScopedAStatus getSlicingConfigResponse(
+            const RadioResponseInfo& info, const SlicingConfig& slicingConfig) override;
+
+    virtual ndk::ScopedAStatus releasePduSessionIdResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setDataAllowedResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setDataProfileResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setDataThrottlingResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setInitialAttachApnResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setupDataCallResponse(
+            const RadioResponseInfo& info, const SetupDataCallResult& dcResponse) override;
+
+    virtual ndk::ScopedAStatus startHandoverResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus startKeepaliveResponse(const RadioResponseInfo& info,
+                                                      const KeepaliveStatus& status) override;
+
+    virtual ndk::ScopedAStatus stopKeepaliveResponse(const RadioResponseInfo& info) override;
+};
+
+/* Callback class for radio data indication */
+class RadioDataIndication : public BnRadioDataIndication {
+  protected:
+    RadioServiceTest& parent_data;
+
+  public:
+    RadioDataIndication(RadioServiceTest& parent_data);
+    virtual ~RadioDataIndication() = default;
+
+    virtual ndk::ScopedAStatus dataCallListChanged(
+            RadioIndicationType type, const std::vector<SetupDataCallResult>& dcList) override;
+
+    virtual ndk::ScopedAStatus keepaliveStatus(RadioIndicationType type,
+                                               const KeepaliveStatus& status) override;
+
+    virtual ndk::ScopedAStatus pcoData(RadioIndicationType type, const PcoDataInfo& pco) override;
+
+    virtual ndk::ScopedAStatus unthrottleApn(RadioIndicationType type,
+                                             const DataProfileInfo& dataProfile) override;
+    virtual ndk::ScopedAStatus slicingConfigChanged(RadioIndicationType type,
+                                                    const SlicingConfig& slicingConfig) override;
+};
+
+// The main test class for Radio AIDL Data.
+class RadioDataTest : public ::testing::TestWithParam<std::string>, public RadioServiceTest {
+  protected:
+    /* Get current data call list */
+    ndk::ScopedAStatus getDataCallList();
+
+  public:
+    virtual void SetUp() override;
+
+    /* radio data service handle */
+    std::shared_ptr<IRadioData> radio_data;
+    /* radio data response handle */
+    std::shared_ptr<RadioDataResponse> radioRsp_data;
+    /* radio data indication handle */
+    std::shared_ptr<RadioDataIndication> radioInd_data;
+};
diff --git a/radio/aidl/vts/radio_messaging_indication.cpp b/radio/aidl/vts/radio_messaging_indication.cpp
new file mode 100644
index 0000000..481239e
--- /dev/null
+++ b/radio/aidl/vts/radio_messaging_indication.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "radio_messaging_utils.h"
+
+RadioMessagingIndication::RadioMessagingIndication(RadioServiceTest& parent)
+    : parent_messaging(parent) {}
+
+ndk::ScopedAStatus RadioMessagingIndication::cdmaNewSms(RadioIndicationType /*type*/,
+                                                        const CdmaSmsMessage& /*msg*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingIndication::cdmaRuimSmsStorageFull(RadioIndicationType /*type*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingIndication::newBroadcastSms(RadioIndicationType /*type*/,
+                                                             const std::vector<uint8_t>& /*data*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingIndication::newSms(RadioIndicationType /*type*/,
+                                                    const std::vector<uint8_t>& /*pdu*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingIndication::newSmsOnSim(RadioIndicationType /*type*/,
+                                                         int32_t /*recordNumber*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingIndication::newSmsStatusReport(
+        RadioIndicationType /*type*/, const std::vector<uint8_t>& /*pdu*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingIndication::simSmsStorageFull(RadioIndicationType /*type*/) {
+    return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_messaging_response.cpp b/radio/aidl/vts/radio_messaging_response.cpp
new file mode 100644
index 0000000..49c0806
--- /dev/null
+++ b/radio/aidl/vts/radio_messaging_response.cpp
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "radio_messaging_utils.h"
+
+RadioMessagingResponse::RadioMessagingResponse(RadioServiceTest& parent)
+    : parent_messaging(parent) {}
+
+ndk::ScopedAStatus RadioMessagingResponse::acknowledgeIncomingGsmSmsWithPduResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_messaging.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::acknowledgeLastIncomingCdmaSmsResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_messaging.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::acknowledgeLastIncomingGsmSmsResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_messaging.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::acknowledgeRequest(int32_t /*serial*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::deleteSmsOnRuimResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_messaging.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::deleteSmsOnSimResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_messaging.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::getCdmaBroadcastConfigResponse(
+        const RadioResponseInfo& info, const std::vector<CdmaBroadcastSmsConfigInfo>& /*configs*/) {
+    rspInfo = info;
+    parent_messaging.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::getGsmBroadcastConfigResponse(
+        const RadioResponseInfo& info, const std::vector<GsmBroadcastSmsConfigInfo>& /*configs*/) {
+    rspInfo = info;
+    parent_messaging.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::getSmscAddressResponse(const RadioResponseInfo& info,
+                                                                  const std::string& /*smsc*/) {
+    rspInfo = info;
+    parent_messaging.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::reportSmsMemoryStatusResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_messaging.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::sendCdmaSmsExpectMoreResponse(
+        const RadioResponseInfo& info, const SendSmsResult& sms) {
+    rspInfo = info;
+    sendSmsResult = sms;
+    parent_messaging.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::sendCdmaSmsResponse(const RadioResponseInfo& info,
+                                                               const SendSmsResult& sms) {
+    rspInfo = info;
+    sendSmsResult = sms;
+    parent_messaging.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::sendImsSmsResponse(const RadioResponseInfo& info,
+                                                              const SendSmsResult& /*sms*/) {
+    rspInfo = info;
+    parent_messaging.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::sendSmsExpectMoreResponse(const RadioResponseInfo& info,
+                                                                     const SendSmsResult& sms) {
+    rspInfo = info;
+    sendSmsResult = sms;
+    parent_messaging.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::sendSmsResponse(const RadioResponseInfo& info,
+                                                           const SendSmsResult& sms) {
+    rspInfo = info;
+    sendSmsResult = sms;
+    parent_messaging.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::setCdmaBroadcastActivationResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_messaging.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::setCdmaBroadcastConfigResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_messaging.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::setGsmBroadcastActivationResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_messaging.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::setGsmBroadcastConfigResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_messaging.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::setSmscAddressResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_messaging.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::writeSmsToRuimResponse(const RadioResponseInfo& info,
+                                                                  int32_t /*index*/) {
+    rspInfo = info;
+    parent_messaging.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioMessagingResponse::writeSmsToSimResponse(const RadioResponseInfo& info,
+                                                                 int32_t /*index*/) {
+    rspInfo = info;
+    parent_messaging.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_messaging_test.cpp b/radio/aidl/vts/radio_messaging_test.cpp
new file mode 100644
index 0000000..9f1718b
--- /dev/null
+++ b/radio/aidl/vts/radio_messaging_test.cpp
@@ -0,0 +1,731 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aidl/android/hardware/radio/config/IRadioConfig.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+
+#include "radio_messaging_utils.h"
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
+
+void RadioMessagingTest::SetUp() {
+    std::string serviceName = GetParam();
+
+    if (!isServiceValidForDeviceConfiguration(serviceName)) {
+        ALOGI("Skipped the test due to device configuration.");
+        GTEST_SKIP();
+    }
+
+    radio_messaging = IRadioMessaging::fromBinder(
+            ndk::SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+    ASSERT_NE(nullptr, radio_messaging.get());
+
+    radioRsp_messaging = ndk::SharedRefBase::make<RadioMessagingResponse>(*this);
+    ASSERT_NE(nullptr, radioRsp_messaging.get());
+
+    count_ = 0;
+
+    radioInd_messaging = ndk::SharedRefBase::make<RadioMessagingIndication>(*this);
+    ASSERT_NE(nullptr, radioInd_messaging.get());
+
+    radio_messaging->setResponseFunctions(radioRsp_messaging, radioInd_messaging);
+
+    // Assert IRadioSim exists and SIM is present before testing
+    radio_sim = sim::IRadioSim::fromBinder(ndk::SpAIBinder(
+            AServiceManager_waitForService("android.hardware.radio.sim.IRadioSim/slot1")));
+    ASSERT_NE(nullptr, radio_sim.get());
+    updateSimCardStatus();
+    EXPECT_EQ(CardStatus::STATE_PRESENT, cardStatus.cardState);
+
+    // Assert IRadioConfig exists before testing
+    radio_config = config::IRadioConfig::fromBinder(ndk::SpAIBinder(
+            AServiceManager_waitForService("android.hardware.radio.config.IRadioConfig/default")));
+    ASSERT_NE(nullptr, radio_config.get());
+}
+
+/*
+ * Test IRadioMessaging.sendSms() for the response returned.
+ */
+TEST_P(RadioMessagingTest, sendSms) {
+    LOG(DEBUG) << "sendSms";
+    serial = GetRandomSerialNumber();
+    GsmSmsMessage msg;
+    msg.smscPdu = "";
+    msg.pdu = "01000b916105770203f3000006d4f29c3e9b01";
+
+    radio_messaging->sendSms(serial, msg);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_messaging->rspInfo.error,
+                {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::SIM_ABSENT},
+                CHECK_GENERAL_ERROR));
+        EXPECT_EQ(0, radioRsp_messaging->sendSmsResult.errorCode);
+    }
+    LOG(DEBUG) << "sendSms finished";
+}
+
+/*
+ * Test IRadioMessaging.sendSmsExpectMore() for the response returned.
+ */
+TEST_P(RadioMessagingTest, sendSmsExpectMore) {
+    LOG(DEBUG) << "sendSmsExpectMore";
+    serial = GetRandomSerialNumber();
+    GsmSmsMessage msg;
+    msg.smscPdu = "";
+    msg.pdu = "01000b916105770203f3000006d4f29c3e9b01";
+
+    radio_messaging->sendSmsExpectMore(serial, msg);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_messaging->rspInfo.error,
+                {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::SIM_ABSENT},
+                CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "sendSmsExpectMore finished";
+}
+
+/*
+ * Test IRadioMessaging.sendCdmaSms() for the response returned.
+ */
+TEST_P(RadioMessagingTest, sendCdmaSms) {
+    LOG(DEBUG) << "sendCdmaSms";
+    serial = GetRandomSerialNumber();
+
+    // Create a CdmaSmsAddress
+    CdmaSmsAddress cdmaSmsAddress;
+    cdmaSmsAddress.digitMode = CdmaSmsAddress::DIGIT_MODE_FOUR_BIT;
+    cdmaSmsAddress.isNumberModeDataNetwork = false;
+    cdmaSmsAddress.numberType = CdmaSmsAddress::NUMBER_TYPE_UNKNOWN;
+    cdmaSmsAddress.numberPlan = CdmaSmsAddress::NUMBER_PLAN_UNKNOWN;
+    cdmaSmsAddress.digits = (std::vector<uint8_t>){11, 1, 6, 5, 10, 7, 7, 2, 10, 3, 10, 3};
+
+    // Create a CdmaSmsSubAddress
+    CdmaSmsSubaddress cdmaSmsSubaddress;
+    cdmaSmsSubaddress.subaddressType = CdmaSmsSubaddress::SUBADDRESS_TYPE_NSAP;
+    cdmaSmsSubaddress.odd = false;
+    cdmaSmsSubaddress.digits = (std::vector<uint8_t>){};
+
+    // Create a CdmaSmsMessage
+    CdmaSmsMessage cdmaSmsMessage;
+    cdmaSmsMessage.teleserviceId = 4098;
+    cdmaSmsMessage.isServicePresent = false;
+    cdmaSmsMessage.serviceCategory = 0;
+    cdmaSmsMessage.address = cdmaSmsAddress;
+    cdmaSmsMessage.subAddress = cdmaSmsSubaddress;
+    cdmaSmsMessage.bearerData =
+            (std::vector<uint8_t>){15, 0, 3, 32, 3, 16, 1, 8, 16, 53, 76, 68, 6, 51, 106, 0};
+
+    radio_messaging->sendCdmaSms(serial, cdmaSmsMessage);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_messaging->rspInfo.error,
+                {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::SIM_ABSENT},
+                CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "sendCdmaSms finished";
+}
+
+/*
+ * Test IRadioMessaging.sendCdmaSmsExpectMore() for the response returned.
+ */
+TEST_P(RadioMessagingTest, sendCdmaSmsExpectMore) {
+    serial = GetRandomSerialNumber();
+
+    // Create a CdmaSmsAddress
+    CdmaSmsAddress cdmaSmsAddress;
+    cdmaSmsAddress.digitMode = CdmaSmsAddress::DIGIT_MODE_FOUR_BIT;
+    cdmaSmsAddress.isNumberModeDataNetwork = false;
+    cdmaSmsAddress.numberType = CdmaSmsAddress::NUMBER_TYPE_UNKNOWN;
+    cdmaSmsAddress.numberPlan = CdmaSmsAddress::NUMBER_PLAN_UNKNOWN;
+    cdmaSmsAddress.digits = (std::vector<uint8_t>){11, 1, 6, 5, 10, 7, 7, 2, 10, 3, 10, 3};
+
+    // Create a CdmaSmsSubAddress
+    CdmaSmsSubaddress cdmaSmsSubaddress;
+    cdmaSmsSubaddress.subaddressType = CdmaSmsSubaddress::SUBADDRESS_TYPE_NSAP;
+    cdmaSmsSubaddress.odd = false;
+    cdmaSmsSubaddress.digits = (std::vector<uint8_t>){};
+
+    // Create a CdmaSmsMessage
+    CdmaSmsMessage cdmaSmsMessage;
+    cdmaSmsMessage.teleserviceId = 4098;
+    cdmaSmsMessage.isServicePresent = false;
+    cdmaSmsMessage.serviceCategory = 0;
+    cdmaSmsMessage.address = cdmaSmsAddress;
+    cdmaSmsMessage.subAddress = cdmaSmsSubaddress;
+    cdmaSmsMessage.bearerData =
+            (std::vector<uint8_t>){15, 0, 3, 32, 3, 16, 1, 8, 16, 53, 76, 68, 6, 51, 106, 0};
+
+    radio_messaging->sendCdmaSmsExpectMore(serial, cdmaSmsMessage);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_messaging->rspInfo.error,
+                {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::SIM_ABSENT},
+                CHECK_GENERAL_ERROR));
+    }
+}
+
+/*
+ * Test IRadioMessaging.setGsmBroadcastConfig() for the response returned.
+ */
+TEST_P(RadioMessagingTest, setGsmBroadcastConfig) {
+    LOG(DEBUG) << "setGsmBroadcastConfig";
+    serial = GetRandomSerialNumber();
+
+    // Create GsmBroadcastSmsConfigInfo #1
+    GsmBroadcastSmsConfigInfo gbSmsConfig1;
+    gbSmsConfig1.fromServiceId = 4352;
+    gbSmsConfig1.toServiceId = 4354;
+    gbSmsConfig1.fromCodeScheme = 0;
+    gbSmsConfig1.toCodeScheme = 255;
+    gbSmsConfig1.selected = true;
+
+    // Create GsmBroadcastSmsConfigInfo #2
+    GsmBroadcastSmsConfigInfo gbSmsConfig2;
+    gbSmsConfig2.fromServiceId = 4356;
+    gbSmsConfig2.toServiceId = 4356;
+    gbSmsConfig2.fromCodeScheme = 0;
+    gbSmsConfig2.toCodeScheme = 255;
+    gbSmsConfig2.selected = true;
+
+    // Create GsmBroadcastSmsConfigInfo #3
+    GsmBroadcastSmsConfigInfo gbSmsConfig3;
+    gbSmsConfig3.fromServiceId = 4370;
+    gbSmsConfig3.toServiceId = 4379;
+    gbSmsConfig3.fromCodeScheme = 0;
+    gbSmsConfig3.toCodeScheme = 255;
+    gbSmsConfig3.selected = true;
+
+    // Create GsmBroadcastSmsConfigInfo #4
+    GsmBroadcastSmsConfigInfo gbSmsConfig4;
+    gbSmsConfig4.fromServiceId = 4383;
+    gbSmsConfig4.toServiceId = 4391;
+    gbSmsConfig4.fromCodeScheme = 0;
+    gbSmsConfig4.toCodeScheme = 255;
+    gbSmsConfig4.selected = true;
+
+    // Create GsmBroadcastSmsConfigInfo #5
+    GsmBroadcastSmsConfigInfo gbSmsConfig5;
+    gbSmsConfig5.fromServiceId = 4392;
+    gbSmsConfig5.toServiceId = 4392;
+    gbSmsConfig5.fromCodeScheme = 0;
+    gbSmsConfig5.toCodeScheme = 255;
+    gbSmsConfig5.selected = true;
+
+    std::vector<GsmBroadcastSmsConfigInfo> gsmBroadcastSmsConfigsInfoList = {
+            gbSmsConfig1, gbSmsConfig2, gbSmsConfig3, gbSmsConfig4, gbSmsConfig5};
+
+    radio_messaging->setGsmBroadcastConfig(serial, gsmBroadcastSmsConfigsInfoList);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_messaging->rspInfo.error,
+                                     {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
+                                      RadioError::INVALID_MODEM_STATE, RadioError::INVALID_STATE},
+                                     CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "setGsmBroadcastConfig finished";
+}
+
+/*
+ * Test IRadioMessaging.getGsmBroadcastConfig() for the response returned.
+ */
+TEST_P(RadioMessagingTest, getGsmBroadcastConfig) {
+    LOG(DEBUG) << "getGsmBroadcastConfig";
+    serial = GetRandomSerialNumber();
+
+    radio_messaging->getGsmBroadcastConfig(serial);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_messaging->rspInfo.error,
+                {RadioError::NONE, RadioError::INVALID_MODEM_STATE, RadioError::INVALID_STATE},
+                CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "getGsmBroadcastConfig finished";
+}
+
+/*
+ * Test IRadioMessaging.setCdmaBroadcastConfig() for the response returned.
+ */
+TEST_P(RadioMessagingTest, setCdmaBroadcastConfig) {
+    LOG(DEBUG) << "setCdmaBroadcastConfig";
+    serial = GetRandomSerialNumber();
+
+    CdmaBroadcastSmsConfigInfo cbSmsConfig;
+    cbSmsConfig.serviceCategory = 4096;
+    cbSmsConfig.language = 1;
+    cbSmsConfig.selected = true;
+
+    std::vector<CdmaBroadcastSmsConfigInfo> cdmaBroadcastSmsConfigInfoList = {cbSmsConfig};
+
+    radio_messaging->setCdmaBroadcastConfig(serial, cdmaBroadcastSmsConfigInfoList);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_messaging->rspInfo.error,
+                                     {RadioError::NONE, RadioError::INVALID_MODEM_STATE},
+                                     CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "setCdmaBroadcastConfig finished";
+}
+
+/*
+ * Test IRadioMessaging.getCdmaBroadcastConfig() for the response returned.
+ */
+TEST_P(RadioMessagingTest, getCdmaBroadcastConfig) {
+    LOG(DEBUG) << "getCdmaBroadcastConfig";
+    serial = GetRandomSerialNumber();
+
+    radio_messaging->getCdmaBroadcastConfig(serial);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_messaging->rspInfo.error, {RadioError::NONE},
+                                     CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "getCdmaBroadcastConfig finished";
+}
+
+/*
+ * Test IRadioMessaging.setCdmaBroadcastActivation() for the response returned.
+ */
+TEST_P(RadioMessagingTest, setCdmaBroadcastActivation) {
+    LOG(DEBUG) << "setCdmaBroadcastActivation";
+    serial = GetRandomSerialNumber();
+    bool activate = false;
+
+    radio_messaging->setCdmaBroadcastActivation(serial, activate);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_messaging->rspInfo.error,
+                                     {RadioError::NONE, RadioError::INVALID_ARGUMENTS},
+                                     CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "setCdmaBroadcastActivation finished";
+}
+
+/*
+ * Test IRadioMessaging.setGsmBroadcastActivation() for the response returned.
+ */
+TEST_P(RadioMessagingTest, setGsmBroadcastActivation) {
+    LOG(DEBUG) << "setGsmBroadcastActivation";
+    serial = GetRandomSerialNumber();
+    bool activate = false;
+
+    radio_messaging->setGsmBroadcastActivation(serial, activate);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_messaging->rspInfo.error,
+                {RadioError::NONE, RadioError::INVALID_ARGUMENTS, RadioError::INVALID_MODEM_STATE,
+                 RadioError::INVALID_STATE, RadioError::OPERATION_NOT_ALLOWED},
+                CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "setGsmBroadcastActivation finished";
+}
+
+/*
+ * Test IRadioMessaging.acknowledgeLastIncomingGsmSms() for the response returned.
+ */
+TEST_P(RadioMessagingTest, acknowledgeLastIncomingGsmSms) {
+    LOG(DEBUG) << "acknowledgeLastIncomingGsmSms";
+    serial = GetRandomSerialNumber();
+    bool success = true;
+
+    radio_messaging->acknowledgeLastIncomingGsmSms(
+            serial, success, SmsAcknowledgeFailCause::MEMORY_CAPACITY_EXCEEDED);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_messaging->rspInfo.error,
+                                     {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE},
+                                     CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "acknowledgeLastIncomingGsmSms finished";
+}
+
+/*
+ * Test IRadioMessaging.acknowledgeIncomingGsmSmsWithPdu() for the response returned.
+ */
+TEST_P(RadioMessagingTest, acknowledgeIncomingGsmSmsWithPdu) {
+    LOG(DEBUG) << "acknowledgeIncomingGsmSmsWithPdu";
+    serial = GetRandomSerialNumber();
+    bool success = true;
+    std::string ackPdu = "";
+
+    radio_messaging->acknowledgeIncomingGsmSmsWithPdu(serial, success, ackPdu);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_messaging->rspInfo.error,
+                                     {RadioError::INVALID_ARGUMENTS, RadioError::NO_SMS_TO_ACK},
+                                     CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "acknowledgeIncomingGsmSmsWithPdu finished";
+}
+
+/*
+ * Test IRadioMessaging.acknowledgeLastIncomingCdmaSms() for the response returned.
+ */
+TEST_P(RadioMessagingTest, acknowledgeLastIncomingCdmaSms) {
+    LOG(DEBUG) << "acknowledgeLastIncomingCdmaSms";
+    serial = GetRandomSerialNumber();
+
+    // Create a CdmaSmsAck
+    CdmaSmsAck cdmaSmsAck;
+    cdmaSmsAck.errorClass = false;
+    cdmaSmsAck.smsCauseCode = 1;
+
+    radio_messaging->acknowledgeLastIncomingCdmaSms(serial, cdmaSmsAck);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_messaging->rspInfo.error,
+                                     {RadioError::INVALID_ARGUMENTS, RadioError::NO_SMS_TO_ACK},
+                                     CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "acknowledgeLastIncomingCdmaSms finished";
+}
+
+/*
+ * Test IRadioMessaging.sendImsSms() for the response returned.
+ */
+TEST_P(RadioMessagingTest, sendImsSms) {
+    LOG(DEBUG) << "sendImsSms";
+    serial = GetRandomSerialNumber();
+
+    // Create a CdmaSmsAddress
+    CdmaSmsAddress cdmaSmsAddress;
+    cdmaSmsAddress.digitMode = CdmaSmsAddress::DIGIT_MODE_FOUR_BIT;
+    cdmaSmsAddress.isNumberModeDataNetwork = false;
+    cdmaSmsAddress.numberType = CdmaSmsAddress::NUMBER_TYPE_UNKNOWN;
+    cdmaSmsAddress.numberPlan = CdmaSmsAddress::NUMBER_PLAN_UNKNOWN;
+    cdmaSmsAddress.digits = (std::vector<uint8_t>){11, 1, 6, 5, 10, 7, 7, 2, 10, 3, 10, 3};
+
+    // Create a CdmaSmsSubAddress
+    CdmaSmsSubaddress cdmaSmsSubaddress;
+    cdmaSmsSubaddress.subaddressType = CdmaSmsSubaddress::SUBADDRESS_TYPE_NSAP;
+    cdmaSmsSubaddress.odd = false;
+    cdmaSmsSubaddress.digits = (std::vector<uint8_t>){};
+
+    // Create a CdmaSmsMessage
+    CdmaSmsMessage cdmaSmsMessage;
+    cdmaSmsMessage.teleserviceId = 4098;
+    cdmaSmsMessage.isServicePresent = false;
+    cdmaSmsMessage.serviceCategory = 0;
+    cdmaSmsMessage.address = cdmaSmsAddress;
+    cdmaSmsMessage.subAddress = cdmaSmsSubaddress;
+    cdmaSmsMessage.bearerData =
+            (std::vector<uint8_t>){15, 0, 3, 32, 3, 16, 1, 8, 16, 53, 76, 68, 6, 51, 106, 0};
+
+    // Creata an ImsSmsMessage
+    ImsSmsMessage msg;
+    msg.tech = RadioTechnologyFamily::THREE_GPP2;
+    msg.retry = false;
+    msg.messageRef = 0;
+    msg.cdmaMessage = (std::vector<CdmaSmsMessage>){cdmaSmsMessage};
+    msg.gsmMessage = (std::vector<GsmSmsMessage>){};
+
+    radio_messaging->sendImsSms(serial, msg);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_messaging->rspInfo.error,
+                                     {RadioError::INVALID_ARGUMENTS}, CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "sendImsSms finished";
+}
+
+/*
+ * Test IRadioMessaging.getSmscAddress() for the response returned.
+ */
+TEST_P(RadioMessagingTest, getSmscAddress) {
+    LOG(DEBUG) << "getSmscAddress";
+    serial = GetRandomSerialNumber();
+
+    radio_messaging->getSmscAddress(serial);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_messaging->rspInfo.error,
+                                     {RadioError::INVALID_MODEM_STATE, RadioError::INVALID_STATE,
+                                      RadioError::SIM_ABSENT},
+                                     CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "getSmscAddress finished";
+}
+
+/*
+ * Test IRadioMessaging.setSmscAddress() for the response returned.
+ */
+TEST_P(RadioMessagingTest, setSmscAddress) {
+    LOG(DEBUG) << "setSmscAddress";
+    serial = GetRandomSerialNumber();
+    std::string address = std::string("smscAddress");
+
+    radio_messaging->setSmscAddress(serial, address);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_messaging->rspInfo.error,
+                                     {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_SMS_FORMAT,
+                                      RadioError::SIM_ABSENT},
+                                     CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "setSmscAddress finished";
+}
+
+/*
+ * Test IRadioMessaging.writeSmsToSim() for the response returned.
+ */
+TEST_P(RadioMessagingTest, writeSmsToSim) {
+    LOG(DEBUG) << "writeSmsToSim";
+    serial = GetRandomSerialNumber();
+    SmsWriteArgs smsWriteArgs;
+    smsWriteArgs.status = SmsWriteArgs::STATUS_REC_UNREAD;
+    smsWriteArgs.smsc = "";
+    smsWriteArgs.pdu = "01000b916105770203f3000006d4f29c3e9b01";
+
+    radio_messaging->writeSmsToSim(serial, smsWriteArgs);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_messaging->rspInfo.error,
+                {RadioError::NONE, RadioError::ENCODING_ERR, RadioError::INVALID_ARGUMENTS,
+                 RadioError::INVALID_SMSC_ADDRESS, RadioError::MODEM_ERR,
+                 RadioError::NETWORK_NOT_READY, RadioError::NO_RESOURCES, RadioError::SIM_ABSENT},
+                CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "writeSmsToSim finished";
+}
+
+/*
+ * Test IRadioMessaging.deleteSmsOnSim() for the response returned.
+ */
+TEST_P(RadioMessagingTest, deleteSmsOnSim) {
+    LOG(DEBUG) << "deleteSmsOnSim";
+    serial = GetRandomSerialNumber();
+    int index = 1;
+
+    radio_messaging->deleteSmsOnSim(serial, index);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_messaging->rspInfo.error,
+                {RadioError::NONE, RadioError::ENCODING_ERR, RadioError::INVALID_ARGUMENTS,
+                 RadioError::INVALID_MODEM_STATE, RadioError::NO_SUCH_ENTRY, RadioError::MODEM_ERR,
+                 RadioError::SIM_ABSENT},
+                CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "deleteSmsOnSim finished";
+}
+
+/*
+ * Test IRadioMessaging.writeSmsToRuim() for the response returned.
+ */
+TEST_P(RadioMessagingTest, writeSmsToRuim) {
+    LOG(DEBUG) << "writeSmsToRuim";
+    serial = GetRandomSerialNumber();
+
+    // Create a CdmaSmsAddress
+    CdmaSmsAddress cdmaSmsAddress;
+    cdmaSmsAddress.digitMode = CdmaSmsAddress::DIGIT_MODE_FOUR_BIT;
+    cdmaSmsAddress.isNumberModeDataNetwork = false;
+    cdmaSmsAddress.numberType = CdmaSmsAddress::NUMBER_TYPE_UNKNOWN;
+    cdmaSmsAddress.numberPlan = CdmaSmsAddress::NUMBER_PLAN_UNKNOWN;
+    cdmaSmsAddress.digits = (std::vector<uint8_t>){11, 1, 6, 5, 10, 7, 7, 2, 10, 3, 10, 3};
+
+    // Create a CdmaSmsSubAddress
+    CdmaSmsSubaddress cdmaSmsSubaddress;
+    cdmaSmsSubaddress.subaddressType = CdmaSmsSubaddress::SUBADDRESS_TYPE_NSAP;
+    cdmaSmsSubaddress.odd = false;
+    cdmaSmsSubaddress.digits = (std::vector<uint8_t>){};
+
+    // Create a CdmaSmsMessage
+    CdmaSmsMessage cdmaSmsMessage;
+    cdmaSmsMessage.teleserviceId = 4098;
+    cdmaSmsMessage.isServicePresent = false;
+    cdmaSmsMessage.serviceCategory = 0;
+    cdmaSmsMessage.address = cdmaSmsAddress;
+    cdmaSmsMessage.subAddress = cdmaSmsSubaddress;
+    cdmaSmsMessage.bearerData =
+            (std::vector<uint8_t>){15, 0, 3, 32, 3, 16, 1, 8, 16, 53, 76, 68, 6, 51, 106, 0};
+
+    // Create a CdmaSmsWriteArgs
+    CdmaSmsWriteArgs cdmaSmsWriteArgs;
+    cdmaSmsWriteArgs.status = CdmaSmsWriteArgs::STATUS_REC_UNREAD;
+    cdmaSmsWriteArgs.message = cdmaSmsMessage;
+
+    radio_messaging->writeSmsToRuim(serial, cdmaSmsWriteArgs);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_messaging->rspInfo.error,
+                {RadioError::NONE, RadioError::INVALID_ARGUMENTS, RadioError::INVALID_SMS_FORMAT,
+                 RadioError::INVALID_SMSC_ADDRESS, RadioError::INVALID_STATE, RadioError::MODEM_ERR,
+                 RadioError::NO_SUCH_ENTRY, RadioError::SIM_ABSENT},
+                CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "writeSmsToRuim finished";
+}
+
+/*
+ * Test IRadioMessaging.deleteSmsOnRuim() for the response returned.
+ */
+TEST_P(RadioMessagingTest, deleteSmsOnRuim) {
+    LOG(DEBUG) << "deleteSmsOnRuim";
+    serial = GetRandomSerialNumber();
+    int index = 1;
+
+    // Create a CdmaSmsAddress
+    CdmaSmsAddress cdmaSmsAddress;
+    cdmaSmsAddress.digitMode = CdmaSmsAddress::DIGIT_MODE_FOUR_BIT;
+    cdmaSmsAddress.isNumberModeDataNetwork = false;
+    cdmaSmsAddress.numberType = CdmaSmsAddress::NUMBER_TYPE_UNKNOWN;
+    cdmaSmsAddress.numberPlan = CdmaSmsAddress::NUMBER_PLAN_UNKNOWN;
+    cdmaSmsAddress.digits = (std::vector<uint8_t>){11, 1, 6, 5, 10, 7, 7, 2, 10, 3, 10, 3};
+
+    // Create a CdmaSmsSubAddress
+    CdmaSmsSubaddress cdmaSmsSubaddress;
+    cdmaSmsSubaddress.subaddressType = CdmaSmsSubaddress::SUBADDRESS_TYPE_NSAP;
+    cdmaSmsSubaddress.odd = false;
+    cdmaSmsSubaddress.digits = (std::vector<uint8_t>){};
+
+    // Create a CdmaSmsMessage
+    CdmaSmsMessage cdmaSmsMessage;
+    cdmaSmsMessage.teleserviceId = 4098;
+    cdmaSmsMessage.isServicePresent = false;
+    cdmaSmsMessage.serviceCategory = 0;
+    cdmaSmsMessage.address = cdmaSmsAddress;
+    cdmaSmsMessage.subAddress = cdmaSmsSubaddress;
+    cdmaSmsMessage.bearerData =
+            (std::vector<uint8_t>){15, 0, 3, 32, 3, 16, 1, 8, 16, 53, 76, 68, 6, 51, 106, 0};
+
+    // Create a CdmaSmsWriteArgs
+    CdmaSmsWriteArgs cdmaSmsWriteArgs;
+    cdmaSmsWriteArgs.status = CdmaSmsWriteArgs::STATUS_REC_UNREAD;
+    cdmaSmsWriteArgs.message = cdmaSmsMessage;
+
+    radio_messaging->deleteSmsOnRuim(serial, index);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_messaging->rspInfo.error,
+                {RadioError::NONE, RadioError::INVALID_ARGUMENTS, RadioError::INVALID_MODEM_STATE,
+                 RadioError::MODEM_ERR, RadioError::NO_SUCH_ENTRY, RadioError::SIM_ABSENT},
+                CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "deleteSmsOnRuim finished";
+}
+
+/*
+ * Test IRadioMessaging.reportSmsMemoryStatus() for the response returned.
+ */
+TEST_P(RadioMessagingTest, reportSmsMemoryStatus) {
+    LOG(DEBUG) << "reportSmsMemoryStatus";
+    serial = GetRandomSerialNumber();
+    bool available = true;
+
+    radio_messaging->reportSmsMemoryStatus(serial, available);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_messaging->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_messaging->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_messaging->rspInfo.error,
+                                     {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE,
+                                      RadioError::MODEM_ERR, RadioError::SIM_ABSENT},
+                                     CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "reportSmsMemoryStatus finished";
+}
diff --git a/radio/aidl/vts/radio_messaging_utils.h b/radio/aidl/vts/radio_messaging_utils.h
new file mode 100644
index 0000000..7b66192
--- /dev/null
+++ b/radio/aidl/vts/radio_messaging_utils.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/radio/messaging/BnRadioMessagingIndication.h>
+#include <aidl/android/hardware/radio/messaging/BnRadioMessagingResponse.h>
+#include <aidl/android/hardware/radio/messaging/IRadioMessaging.h>
+
+#include "radio_aidl_hal_utils.h"
+
+using namespace aidl::android::hardware::radio::messaging;
+
+class RadioMessagingTest;
+
+/* Callback class for radio messaging response */
+class RadioMessagingResponse : public BnRadioMessagingResponse {
+  protected:
+    RadioServiceTest& parent_messaging;
+
+  public:
+    RadioMessagingResponse(RadioServiceTest& parent_messaging);
+    virtual ~RadioMessagingResponse() = default;
+
+    RadioResponseInfo rspInfo;
+    SendSmsResult sendSmsResult;
+
+    virtual ndk::ScopedAStatus acknowledgeIncomingGsmSmsWithPduResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus acknowledgeLastIncomingCdmaSmsResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus acknowledgeLastIncomingGsmSmsResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus acknowledgeRequest(int32_t serial) override;
+
+    virtual ndk::ScopedAStatus deleteSmsOnRuimResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus deleteSmsOnSimResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus getCdmaBroadcastConfigResponse(
+            const RadioResponseInfo& info,
+            const std::vector<CdmaBroadcastSmsConfigInfo>& configs) override;
+
+    virtual ndk::ScopedAStatus getGsmBroadcastConfigResponse(
+            const RadioResponseInfo& info,
+            const std::vector<GsmBroadcastSmsConfigInfo>& configs) override;
+
+    virtual ndk::ScopedAStatus getSmscAddressResponse(const RadioResponseInfo& info,
+                                                      const std::string& smsc) override;
+
+    virtual ndk::ScopedAStatus reportSmsMemoryStatusResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus sendCdmaSmsExpectMoreResponse(const RadioResponseInfo& info,
+                                                             const SendSmsResult& sms) override;
+
+    virtual ndk::ScopedAStatus sendCdmaSmsResponse(const RadioResponseInfo& info,
+                                                   const SendSmsResult& sms) override;
+
+    virtual ndk::ScopedAStatus sendImsSmsResponse(const RadioResponseInfo& info,
+                                                  const SendSmsResult& sms) override;
+
+    virtual ndk::ScopedAStatus sendSmsExpectMoreResponse(const RadioResponseInfo& info,
+                                                         const SendSmsResult& sms) override;
+
+    virtual ndk::ScopedAStatus sendSmsResponse(const RadioResponseInfo& info,
+                                               const SendSmsResult& sms) override;
+
+    virtual ndk::ScopedAStatus setCdmaBroadcastActivationResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setCdmaBroadcastConfigResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setGsmBroadcastActivationResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setGsmBroadcastConfigResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setSmscAddressResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus writeSmsToRuimResponse(const RadioResponseInfo& info,
+                                                      int32_t index) override;
+
+    virtual ndk::ScopedAStatus writeSmsToSimResponse(const RadioResponseInfo& info,
+                                                     int32_t index) override;
+};
+
+/* Callback class for radio messaging indication */
+class RadioMessagingIndication : public BnRadioMessagingIndication {
+  protected:
+    RadioServiceTest& parent_messaging;
+
+  public:
+    RadioMessagingIndication(RadioServiceTest& parent_messaging);
+    virtual ~RadioMessagingIndication() = default;
+
+    virtual ndk::ScopedAStatus cdmaNewSms(RadioIndicationType type,
+                                          const CdmaSmsMessage& msg) override;
+
+    virtual ndk::ScopedAStatus cdmaRuimSmsStorageFull(RadioIndicationType type) override;
+
+    virtual ndk::ScopedAStatus newBroadcastSms(RadioIndicationType type,
+                                               const std::vector<uint8_t>& data) override;
+
+    virtual ndk::ScopedAStatus newSms(RadioIndicationType type,
+                                      const std::vector<uint8_t>& pdu) override;
+
+    virtual ndk::ScopedAStatus newSmsOnSim(RadioIndicationType type, int32_t recordNumber) override;
+
+    virtual ndk::ScopedAStatus newSmsStatusReport(RadioIndicationType type,
+                                                  const std::vector<uint8_t>& pdu) override;
+
+    virtual ndk::ScopedAStatus simSmsStorageFull(RadioIndicationType type) override;
+};
+
+// The main test class for Radio AIDL Messaging.
+class RadioMessagingTest : public ::testing::TestWithParam<std::string>, public RadioServiceTest {
+  public:
+    virtual void SetUp() override;
+
+    /* radio messaging service handle */
+    std::shared_ptr<IRadioMessaging> radio_messaging;
+    /* radio messaging response handle */
+    std::shared_ptr<RadioMessagingResponse> radioRsp_messaging;
+    /* radio messaging indication handle */
+    std::shared_ptr<RadioMessagingIndication> radioInd_messaging;
+};
diff --git a/radio/aidl/vts/radio_modem_indication.cpp b/radio/aidl/vts/radio_modem_indication.cpp
new file mode 100644
index 0000000..0bfcd66
--- /dev/null
+++ b/radio/aidl/vts/radio_modem_indication.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "radio_modem_utils.h"
+
+RadioModemIndication::RadioModemIndication(RadioServiceTest& parent) : parent_modem(parent) {}
+
+ndk::ScopedAStatus RadioModemIndication::hardwareConfigChanged(
+        RadioIndicationType /*type*/, const std::vector<HardwareConfig>& /*configs*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemIndication::modemReset(RadioIndicationType /*type*/,
+                                                    const std::string& /*reason*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemIndication::radioCapabilityIndication(RadioIndicationType /*type*/,
+                                                                   const RadioCapability& /*rc*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemIndication::radioStateChanged(RadioIndicationType /*type*/,
+                                                           RadioState /*radioState*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemIndication::rilConnected(RadioIndicationType /*type*/) {
+    return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_modem_response.cpp b/radio/aidl/vts/radio_modem_response.cpp
new file mode 100644
index 0000000..20b44c5
--- /dev/null
+++ b/radio/aidl/vts/radio_modem_response.cpp
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "radio_modem_utils.h"
+
+RadioModemResponse::RadioModemResponse(RadioServiceTest& parent) : parent_modem(parent) {}
+
+ndk::ScopedAStatus RadioModemResponse::acknowledgeRequest(int32_t /*serial*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::enableModemResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    enableModemResponseToggle = !enableModemResponseToggle;
+    parent_modem.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::getBasebandVersionResponse(const RadioResponseInfo& info,
+                                                                  const std::string& /*version*/) {
+    rspInfo = info;
+    parent_modem.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::getDeviceIdentityResponse(const RadioResponseInfo& info,
+                                                                 const std::string& /*imei*/,
+                                                                 const std::string& /*imeisv*/,
+                                                                 const std::string& /*esn*/,
+                                                                 const std::string& /*meid*/) {
+    rspInfo = info;
+    parent_modem.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::getHardwareConfigResponse(
+        const RadioResponseInfo& info, const std::vector<HardwareConfig>& /*config*/) {
+    rspInfo = info;
+    parent_modem.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::getModemActivityInfoResponse(
+        const RadioResponseInfo& info, const ActivityStatsInfo& /*activityInfo*/) {
+    rspInfo = info;
+    parent_modem.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::getModemStackStatusResponse(const RadioResponseInfo& info,
+                                                                   const bool enabled) {
+    rspInfo = info;
+    isModemEnabled = enabled;
+    parent_modem.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::getRadioCapabilityResponse(const RadioResponseInfo& info,
+                                                                  const RadioCapability& /*rc*/) {
+    rspInfo = info;
+    parent_modem.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::nvReadItemResponse(const RadioResponseInfo& info,
+                                                          const std::string& /*result*/) {
+    rspInfo = info;
+    parent_modem.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::nvResetConfigResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_modem.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::nvWriteCdmaPrlResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_modem.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::nvWriteItemResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_modem.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::requestShutdownResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_modem.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::sendDeviceStateResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_modem.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::setRadioCapabilityResponse(const RadioResponseInfo& info,
+                                                                  const RadioCapability& /*rc*/) {
+    rspInfo = info;
+    parent_modem.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioModemResponse::setRadioPowerResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_modem.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_modem_test.cpp b/radio/aidl/vts/radio_modem_test.cpp
new file mode 100644
index 0000000..f88da13
--- /dev/null
+++ b/radio/aidl/vts/radio_modem_test.cpp
@@ -0,0 +1,387 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aidl/android/hardware/radio/config/IRadioConfig.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+
+#include "radio_modem_utils.h"
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
+
+void RadioModemTest::SetUp() {
+    std::string serviceName = GetParam();
+
+    if (!isServiceValidForDeviceConfiguration(serviceName)) {
+        ALOGI("Skipped the test due to device configuration.");
+        GTEST_SKIP();
+    }
+
+    radio_modem = IRadioModem::fromBinder(
+            ndk::SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+    ASSERT_NE(nullptr, radio_modem.get());
+
+    radioRsp_modem = ndk::SharedRefBase::make<RadioModemResponse>(*this);
+    ASSERT_NE(nullptr, radioRsp_modem.get());
+
+    count_ = 0;
+
+    radioInd_modem = ndk::SharedRefBase::make<RadioModemIndication>(*this);
+    ASSERT_NE(nullptr, radioInd_modem.get());
+
+    radio_modem->setResponseFunctions(radioRsp_modem, radioInd_modem);
+
+    // Assert IRadioSim exists and SIM is present before testing
+    radio_sim = sim::IRadioSim::fromBinder(ndk::SpAIBinder(
+            AServiceManager_waitForService("android.hardware.radio.sim.IRadioSim/slot1")));
+    ASSERT_NE(nullptr, radio_sim.get());
+    updateSimCardStatus();
+    EXPECT_EQ(CardStatus::STATE_PRESENT, cardStatus.cardState);
+
+    // Assert IRadioConfig exists before testing
+    radio_config = config::IRadioConfig::fromBinder(ndk::SpAIBinder(
+            AServiceManager_waitForService("android.hardware.radio.config.IRadioConfig/default")));
+    ASSERT_NE(nullptr, radio_config.get());
+}
+
+/*
+ * Test IRadioModem.setRadioPower() for the response returned.
+ */
+TEST_P(RadioModemTest, setRadioPower_emergencyCall_cancelled) {
+    // Set radio power to off.
+    serial = GetRandomSerialNumber();
+    radio_modem->setRadioPower(serial, false, false, false);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+    EXPECT_EQ(RadioError::NONE, radioRsp_modem->rspInfo.error);
+
+    // Set radio power to on with forEmergencyCall being true. This should put modem to only scan
+    // emergency call bands.
+    serial = GetRandomSerialNumber();
+    radio_modem->setRadioPower(serial, true, true, true);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+    EXPECT_EQ(RadioError::NONE, radioRsp_modem->rspInfo.error);
+
+    // Set radio power to on with forEmergencyCall being false. This should put modem in regular
+    // operation modem.
+    serial = GetRandomSerialNumber();
+    radio_modem->setRadioPower(serial, true, false, false);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+    EXPECT_EQ(RadioError::NONE, radioRsp_modem->rspInfo.error);
+}
+
+/*
+ * Test IRadioModem.enableModem() for the response returned.
+ */
+TEST_P(RadioModemTest, enableModem) {
+    serial = GetRandomSerialNumber();
+
+    if (isSsSsEnabled()) {
+        ALOGI("enableModem, no need to test in single SIM mode");
+        return;
+    }
+
+    bool responseToggle = radioRsp_modem->enableModemResponseToggle;
+    ndk::ScopedAStatus res = radio_modem->enableModem(serial, true);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+    ALOGI("getModemStackStatus, rspInfo.error = %s\n",
+          toString(radioRsp_modem->rspInfo.error).c_str());
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_modem->rspInfo.error,
+                                 {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
+                                  RadioError::MODEM_ERR, RadioError::INVALID_STATE}));
+
+    // checking if getModemStackStatus returns true, as modem was enabled above
+    if (RadioError::NONE == radioRsp_modem->rspInfo.error) {
+        // wait until modem enabling is finished
+        while (responseToggle == radioRsp_modem->enableModemResponseToggle) {
+            sleep(1);
+        }
+        ndk::ScopedAStatus resEnabled = radio_modem->getModemStackStatus(serial);
+        ASSERT_OK(resEnabled);
+        EXPECT_EQ(std::cv_status::no_timeout, wait());
+        EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+        EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+        ALOGI("getModemStackStatus, rspInfo.error = %s\n",
+              toString(radioRsp_modem->rspInfo.error).c_str());
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_modem->rspInfo.error,
+                                     {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
+                                      RadioError::MODEM_ERR, RadioError::INVALID_STATE}));
+        // verify that enableModem did set isEnabled correctly
+        EXPECT_EQ(true, radioRsp_modem->isModemEnabled);
+    }
+}
+
+/*
+ * Test IRadioModem.getModemStackStatus() for the response returned.
+ */
+TEST_P(RadioModemTest, getModemStackStatus) {
+    serial = GetRandomSerialNumber();
+
+    ndk::ScopedAStatus res = radio_modem->getModemStackStatus(serial);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+    ALOGI("getModemStackStatus, rspInfo.error = %s\n",
+          toString(radioRsp_modem->rspInfo.error).c_str());
+    ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp_modem->rspInfo.error,
+            {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::MODEM_ERR}));
+}
+
+/*
+ * Test IRadioModem.getBasebandVersion() for the response returned.
+ */
+TEST_P(RadioModemTest, getBasebandVersion) {
+    LOG(DEBUG) << "getBasebandVersion";
+    serial = GetRandomSerialNumber();
+
+    radio_modem->getBasebandVersion(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        EXPECT_EQ(RadioError::NONE, radioRsp_modem->rspInfo.error);
+    }
+    LOG(DEBUG) << "getBasebandVersion finished";
+}
+
+/*
+ * Test IRadioModem.getDeviceIdentity() for the response returned.
+ */
+TEST_P(RadioModemTest, getDeviceIdentity) {
+    LOG(DEBUG) << "getDeviceIdentity";
+    serial = GetRandomSerialNumber();
+
+    radio_modem->getDeviceIdentity(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_modem->rspInfo.error,
+                                     {RadioError::NONE, RadioError::EMPTY_RECORD}));
+    }
+    LOG(DEBUG) << "getDeviceIdentity finished";
+}
+
+/*
+ * Test IRadioModem.nvReadItem() for the response returned.
+ */
+TEST_P(RadioModemTest, nvReadItem) {
+    LOG(DEBUG) << "nvReadItem";
+    serial = GetRandomSerialNumber();
+
+    radio_modem->nvReadItem(serial, NvItem::LTE_BAND_ENABLE_25);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_modem->rspInfo.error, {RadioError::NONE},
+                                     CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "nvReadItem finished";
+}
+
+/*
+ * Test IRadioModem.nvWriteItem() for the response returned.
+ */
+TEST_P(RadioModemTest, nvWriteItem) {
+    LOG(DEBUG) << "nvWriteItem";
+    serial = GetRandomSerialNumber();
+    NvWriteItem item;
+    memset(&item, 0, sizeof(item));
+    item.value = std::string();
+
+    radio_modem->nvWriteItem(serial, item);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_modem->rspInfo.error, {RadioError::NONE},
+                                     CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "nvWriteItem finished";
+}
+
+/*
+ * Test IRadioModem.nvWriteCdmaPrl() for the response returned.
+ */
+TEST_P(RadioModemTest, nvWriteCdmaPrl) {
+    LOG(DEBUG) << "nvWriteCdmaPrl";
+    serial = GetRandomSerialNumber();
+    std::vector<uint8_t> prl = {1, 2, 3, 4, 5};
+
+    radio_modem->nvWriteCdmaPrl(serial, std::vector<uint8_t>(prl));
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_modem->rspInfo.error, {RadioError::NONE},
+                                     CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "nvWriteCdmaPrl finished";
+}
+
+/*
+ * Test IRadioModem.nvResetConfig() for the response returned.
+ */
+TEST_P(RadioModemTest, nvResetConfig) {
+    LOG(DEBUG) << "nvResetConfig";
+    serial = GetRandomSerialNumber();
+
+    radio_modem->nvResetConfig(serial, ResetNvType::FACTORY_RESET);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_modem->rspInfo.error,
+                                     {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+    }
+    LOG(DEBUG) << "nvResetConfig finished";
+}
+
+/*
+ * Test IRadioModem.getHardwareConfig() for the response returned.
+ */
+TEST_P(RadioModemTest, getHardwareConfig) {
+    LOG(DEBUG) << "getHardwareConfig";
+    serial = GetRandomSerialNumber();
+
+    radio_modem->getHardwareConfig(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_modem->rspInfo.error, {RadioError::NONE},
+                                     CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "getHardwareConfig finished";
+}
+
+/*
+ * The following test is disabled due to b/64734869
+ *
+ * Test IRadioModem.requestShutdown() for the response returned.
+ */
+TEST_P(RadioModemTest, DISABLED_requestShutdown) {
+    serial = GetRandomSerialNumber();
+
+    radio_modem->requestShutdown(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_modem->rspInfo.error, {RadioError::NONE},
+                                     CHECK_GENERAL_ERROR));
+    }
+}
+
+/*
+ * Test IRadioModem.getRadioCapability() for the response returned.
+ */
+TEST_P(RadioModemTest, getRadioCapability) {
+    LOG(DEBUG) << "getRadioCapability";
+    serial = GetRandomSerialNumber();
+
+    radio_modem->getRadioCapability(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        EXPECT_EQ(RadioError::NONE, radioRsp_modem->rspInfo.error);
+    }
+    LOG(DEBUG) << "getRadioCapability finished";
+}
+
+/*
+ * Test IRadioModem.setRadioCapability() for the response returned.
+ */
+TEST_P(RadioModemTest, setRadioCapability) {
+    LOG(DEBUG) << "setRadioCapability";
+    serial = GetRandomSerialNumber();
+    RadioCapability rc;
+    memset(&rc, 0, sizeof(rc));
+    rc.logicalModemUuid = std::string();
+
+    radio_modem->setRadioCapability(serial, rc);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_modem->rspInfo.error,
+                                     {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE},
+                                     CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "setRadioCapability finished";
+}
+
+/*
+ * Test IRadioModem.getModemActivityInfo() for the response returned.
+ */
+TEST_P(RadioModemTest, getModemActivityInfo) {
+    LOG(DEBUG) << "getModemActivityInfo";
+    serial = GetRandomSerialNumber();
+
+    radio_modem->getModemActivityInfo(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_modem->rspInfo.error,
+                                     {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+    }
+    LOG(DEBUG) << "getModemActivityInfo finished";
+}
+
+/*
+ * Test IRadioModem.sendDeviceState() for the response returned.
+ */
+TEST_P(RadioModemTest, sendDeviceState) {
+    LOG(DEBUG) << "sendDeviceState";
+    serial = GetRandomSerialNumber();
+
+    radio_modem->sendDeviceState(serial, DeviceStateType::POWER_SAVE_MODE, true);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_modem->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_modem->rspInfo.serial);
+
+    std::cout << static_cast<int>(radioRsp_modem->rspInfo.error) << std::endl;
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_modem->rspInfo.error,
+                                     {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+    }
+    LOG(DEBUG) << "sendDeviceState finished";
+}
diff --git a/radio/aidl/vts/radio_modem_utils.h b/radio/aidl/vts/radio_modem_utils.h
new file mode 100644
index 0000000..49e1891
--- /dev/null
+++ b/radio/aidl/vts/radio_modem_utils.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/radio/modem/BnRadioModemIndication.h>
+#include <aidl/android/hardware/radio/modem/BnRadioModemResponse.h>
+#include <aidl/android/hardware/radio/modem/IRadioModem.h>
+
+#include "radio_aidl_hal_utils.h"
+
+using namespace aidl::android::hardware::radio::modem;
+
+class RadioModemTest;
+
+/* Callback class for radio modem response */
+class RadioModemResponse : public BnRadioModemResponse {
+  protected:
+    RadioServiceTest& parent_modem;
+
+  public:
+    RadioModemResponse(RadioServiceTest& parent_modem);
+    virtual ~RadioModemResponse() = default;
+
+    RadioResponseInfo rspInfo;
+    bool isModemEnabled;
+    bool enableModemResponseToggle = false;
+
+    virtual ndk::ScopedAStatus acknowledgeRequest(int32_t serial) override;
+
+    virtual ndk::ScopedAStatus enableModemResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus getBasebandVersionResponse(const RadioResponseInfo& info,
+                                                          const std::string& version) override;
+
+    virtual ndk::ScopedAStatus getDeviceIdentityResponse(const RadioResponseInfo& info,
+                                                         const std::string& imei,
+                                                         const std::string& imeisv,
+                                                         const std::string& esn,
+                                                         const std::string& meid) override;
+
+    virtual ndk::ScopedAStatus getHardwareConfigResponse(
+            const RadioResponseInfo& info, const std::vector<HardwareConfig>& config) override;
+
+    virtual ndk::ScopedAStatus getModemActivityInfoResponse(
+            const RadioResponseInfo& info, const ActivityStatsInfo& activityInfo) override;
+
+    virtual ndk::ScopedAStatus getModemStackStatusResponse(const RadioResponseInfo& info,
+                                                           const bool enabled) override;
+
+    virtual ndk::ScopedAStatus getRadioCapabilityResponse(const RadioResponseInfo& info,
+                                                          const RadioCapability& rc) override;
+
+    virtual ndk::ScopedAStatus nvReadItemResponse(const RadioResponseInfo& info,
+                                                  const std::string& result) override;
+
+    virtual ndk::ScopedAStatus nvResetConfigResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus nvWriteCdmaPrlResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus nvWriteItemResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus requestShutdownResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus sendDeviceStateResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setRadioCapabilityResponse(const RadioResponseInfo& info,
+                                                          const RadioCapability& rc) override;
+
+    virtual ndk::ScopedAStatus setRadioPowerResponse(const RadioResponseInfo& info) override;
+};
+
+/* Callback class for radio modem indication */
+class RadioModemIndication : public BnRadioModemIndication {
+  protected:
+    RadioServiceTest& parent_modem;
+
+  public:
+    RadioModemIndication(RadioServiceTest& parent_modem);
+    virtual ~RadioModemIndication() = default;
+
+    virtual ndk::ScopedAStatus hardwareConfigChanged(
+            RadioIndicationType type, const std::vector<HardwareConfig>& configs) override;
+
+    virtual ndk::ScopedAStatus modemReset(RadioIndicationType type,
+                                          const std::string& reason) override;
+
+    virtual ndk::ScopedAStatus radioCapabilityIndication(RadioIndicationType type,
+                                                         const RadioCapability& rc) override;
+
+    virtual ndk::ScopedAStatus radioStateChanged(RadioIndicationType type,
+                                                 RadioState radioState) override;
+
+    virtual ndk::ScopedAStatus rilConnected(RadioIndicationType type) override;
+};
+
+// The main test class for Radio AIDL Modem.
+class RadioModemTest : public ::testing::TestWithParam<std::string>, public RadioServiceTest {
+  public:
+    virtual void SetUp() override;
+
+    /* radio modem service handle */
+    std::shared_ptr<IRadioModem> radio_modem;
+    /* radio modem response handle */
+    std::shared_ptr<RadioModemResponse> radioRsp_modem;
+    /* radio modem indication handle */
+    std::shared_ptr<RadioModemIndication> radioInd_modem;
+};
diff --git a/radio/aidl/vts/radio_network_indication.cpp b/radio/aidl/vts/radio_network_indication.cpp
new file mode 100644
index 0000000..7acbff4
--- /dev/null
+++ b/radio/aidl/vts/radio_network_indication.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "radio_network_utils.h"
+
+RadioNetworkIndication::RadioNetworkIndication(RadioServiceTest& parent) : parent_network(parent) {}
+
+ndk::ScopedAStatus RadioNetworkIndication::barringInfoChanged(
+        RadioIndicationType /*type*/, const CellIdentity& /*cellIdentity*/,
+        const std::vector<BarringInfo>& /*barringInfos*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::cdmaPrlChanged(RadioIndicationType /*type*/,
+                                                          int32_t /*version*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::cellInfoList(RadioIndicationType /*type*/,
+                                                        const std::vector<CellInfo>& /*records*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::currentLinkCapacityEstimate(
+        RadioIndicationType /*type*/, const LinkCapacityEstimate& /*lce*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::currentPhysicalChannelConfigs(
+        RadioIndicationType /*type*/, const std::vector<PhysicalChannelConfig>& /*configs*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::currentSignalStrength(
+        RadioIndicationType /*type*/, const SignalStrength& /*signalStrength*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::imsNetworkStateChanged(RadioIndicationType /*type*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::networkScanResult(RadioIndicationType /*type*/,
+                                                             const NetworkScanResult& /*result*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::networkStateChanged(RadioIndicationType /*type*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::nitzTimeReceived(RadioIndicationType /*type*/,
+                                                            const std::string& /*nitzTime*/,
+                                                            int64_t /*receivedTime*/,
+                                                            int64_t /*age*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::registrationFailed(RadioIndicationType /*type*/,
+                                                              const CellIdentity& /*cellIdentity*/,
+                                                              const std::string& /*chosenPlmn*/,
+                                                              int32_t /*domain*/,
+                                                              int32_t /*causeCode*/,
+                                                              int32_t /*additionalCauseCode*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::restrictedStateChanged(RadioIndicationType /*type*/,
+                                                                  PhoneRestrictedState /*state*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::suppSvcNotify(RadioIndicationType /*type*/,
+                                                         const SuppSvcNotification& /*suppSvc*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkIndication::voiceRadioTechChanged(RadioIndicationType /*type*/,
+                                                                 RadioTechnology /*rat*/) {
+    return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_network_response.cpp b/radio/aidl/vts/radio_network_response.cpp
new file mode 100644
index 0000000..666d617
--- /dev/null
+++ b/radio/aidl/vts/radio_network_response.cpp
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "radio_network_utils.h"
+
+RadioNetworkResponse::RadioNetworkResponse(RadioServiceTest& parent) : parent_network(parent) {}
+
+ndk::ScopedAStatus RadioNetworkResponse::acknowledgeRequest(int32_t /*serial*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getAllowedNetworkTypesBitmapResponse(
+        const RadioResponseInfo& info, const int32_t networkTypeBitmap) {
+    rspInfo = info;
+    networkTypeBitmapResponse = networkTypeBitmap;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getAvailableBandModesResponse(
+        const RadioResponseInfo& info, const std::vector<RadioBandMode>& bandModes) {
+    rspInfo = info;
+    radioBandModes = bandModes;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getAvailableNetworksResponse(
+        const RadioResponseInfo& info, const std::vector<OperatorInfo>& operatorInfos) {
+    rspInfo = info;
+    networkInfos = operatorInfos;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getBarringInfoResponse(
+        const RadioResponseInfo& info, const CellIdentity& cellIdentity,
+        const std::vector<BarringInfo>& barringInfos) {
+    rspInfo = info;
+    barringCellIdentity = cellIdentity;
+    barringInfoList = barringInfos;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getCdmaRoamingPreferenceResponse(
+        const RadioResponseInfo& info, CdmaRoamingType /*type*/) {
+    rspInfo = info;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getCellInfoListResponse(
+        const RadioResponseInfo& info, const std::vector<CellInfo>& /*cellInfo*/) {
+    rspInfo = info;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getDataRegistrationStateResponse(
+        const RadioResponseInfo& info, const RegStateResult& regResponse) {
+    rspInfo = info;
+    dataRegResp = regResponse;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getImsRegistrationStateResponse(
+        const RadioResponseInfo& info, bool /*isRegistered*/, RadioTechnologyFamily /*ratFamily*/) {
+    rspInfo = info;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getNetworkSelectionModeResponse(
+        const RadioResponseInfo& info, bool /*manual*/) {
+    rspInfo = info;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getOperatorResponse(const RadioResponseInfo& info,
+                                                             const std::string& /*longName*/,
+                                                             const std::string& /*shortName*/,
+                                                             const std::string& /*numeric*/) {
+    rspInfo = info;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getSignalStrengthResponse(
+        const RadioResponseInfo& info, const SignalStrength& /*sig_strength*/) {
+    rspInfo = info;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getSystemSelectionChannelsResponse(
+        const RadioResponseInfo& info, const std::vector<RadioAccessSpecifier>& /*specifier*/) {
+    rspInfo = info;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getUsageSettingResponse(const RadioResponseInfo& info,
+                                                                 const UsageSetting usageSetting) {
+    rspInfo = info;
+    this->usageSetting = usageSetting;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getVoiceRadioTechnologyResponse(
+        const RadioResponseInfo& info, RadioTechnology /*rat*/) {
+    rspInfo = info;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getVoiceRegistrationStateResponse(
+        const RadioResponseInfo& info, const RegStateResult& regResponse) {
+    rspInfo = info;
+    voiceRegResp = regResponse;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::isNrDualConnectivityEnabledResponse(
+        const RadioResponseInfo& info, bool isEnabled) {
+    rspInfo = info;
+    isNrDualConnectivityEnabled = isEnabled;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setAllowedNetworkTypesBitmapResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setBandModeResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setBarringPasswordResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setCdmaRoamingPreferenceResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setCellInfoListRateResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setIndicationFilterResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setLinkCapacityReportingCriteriaResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setLocationUpdatesResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setNetworkSelectionModeAutomaticResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setNetworkSelectionModeManualResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setNrDualConnectivityStateResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setSignalStrengthReportingCriteriaResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setSuppServiceNotificationsResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setSystemSelectionChannelsResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setUsageSettingResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::startNetworkScanResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::stopNetworkScanResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::supplyNetworkDepersonalizationResponse(
+        const RadioResponseInfo& info, int32_t /*remainingRetries*/) {
+    rspInfo = info;
+    parent_network.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_network_test.cpp b/radio/aidl/vts/radio_network_test.cpp
new file mode 100644
index 0000000..0bae374
--- /dev/null
+++ b/radio/aidl/vts/radio_network_test.cpp
@@ -0,0 +1,1819 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aidl/android/hardware/radio/RadioAccessFamily.h>
+#include <aidl/android/hardware/radio/config/IRadioConfig.h>
+#include <aidl/android/hardware/radio/network/IndicationFilter.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+
+#include "radio_network_utils.h"
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
+
+void RadioNetworkTest::SetUp() {
+    std::string serviceName = GetParam();
+
+    if (!isServiceValidForDeviceConfiguration(serviceName)) {
+        ALOGI("Skipped the test due to device configuration.");
+        GTEST_SKIP();
+    }
+
+    radio_network = IRadioNetwork::fromBinder(
+            ndk::SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+    ASSERT_NE(nullptr, radio_network.get());
+
+    radioRsp_network = ndk::SharedRefBase::make<RadioNetworkResponse>(*this);
+    ASSERT_NE(nullptr, radioRsp_network.get());
+
+    count_ = 0;
+
+    radioInd_network = ndk::SharedRefBase::make<RadioNetworkIndication>(*this);
+    ASSERT_NE(nullptr, radioInd_network.get());
+
+    radio_network->setResponseFunctions(radioRsp_network, radioInd_network);
+
+    // Assert IRadioSim exists and SIM is present before testing
+    radio_sim = sim::IRadioSim::fromBinder(ndk::SpAIBinder(
+            AServiceManager_waitForService("android.hardware.radio.sim.IRadioSim/slot1")));
+    ASSERT_NE(nullptr, radio_sim.get());
+    updateSimCardStatus();
+    EXPECT_EQ(CardStatus::STATE_PRESENT, cardStatus.cardState);
+
+    // Assert IRadioConfig exists before testing
+    radio_config = config::IRadioConfig::fromBinder(ndk::SpAIBinder(
+            AServiceManager_waitForService("android.hardware.radio.config.IRadioConfig/default")));
+    ASSERT_NE(nullptr, radio_config.get());
+}
+
+void RadioNetworkTest::stopNetworkScan() {
+    serial = GetRandomSerialNumber();
+    radio_network->stopNetworkScan(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+}
+
+/*
+ * Test IRadioNetwork.setAllowedNetworkTypesBitmap for the response returned.
+ */
+TEST_P(RadioNetworkTest, setAllowedNetworkTypesBitmap) {
+    serial = GetRandomSerialNumber();
+    int32_t allowedNetworkTypesBitmap = static_cast<int32_t>(RadioAccessFamily::LTE);
+
+    radio_network->setAllowedNetworkTypesBitmap(serial, allowedNetworkTypesBitmap);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+    ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp_network->rspInfo.error,
+            {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::OPERATION_NOT_ALLOWED,
+             RadioError::MODE_NOT_SUPPORTED, RadioError::INTERNAL_ERR, RadioError::MODEM_ERR,
+             RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED,
+             RadioError::NO_RESOURCES}));
+}
+
+/*
+ * Test IRadioNetwork.getAllowedNetworkTypesBitmap for the response returned.
+ */
+TEST_P(RadioNetworkTest, getAllowedNetworkTypesBitmap) {
+    serial = GetRandomSerialNumber();
+    int32_t allowedNetworkTypesBitmap = static_cast<int32_t>(RadioAccessFamily::LTE);
+
+    radio_network->setAllowedNetworkTypesBitmap(serial, allowedNetworkTypesBitmap);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    if (radioRsp_network->rspInfo.error == RadioError::NONE) {
+        sleep(3);  // wait for modem
+        serial = GetRandomSerialNumber();
+        radio_network->getAllowedNetworkTypesBitmap(serial);
+
+        EXPECT_EQ(std::cv_status::no_timeout, wait());
+        EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+        EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_network->rspInfo.error,
+                {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::INTERNAL_ERR,
+                 RadioError::OPERATION_NOT_ALLOWED, RadioError::MODE_NOT_SUPPORTED,
+                 RadioError::INVALID_ARGUMENTS, RadioError::MODEM_ERR,
+                 RadioError::REQUEST_NOT_SUPPORTED, RadioError::NO_RESOURCES}));
+    }
+}
+
+/*
+ * Test IRadioNetwork.setNrDualConnectivityState() for the response returned.
+ */
+TEST_P(RadioNetworkTest, setNrDualConnectivityState) {
+    serial = GetRandomSerialNumber();
+
+    ndk::ScopedAStatus res =
+            radio_network->setNrDualConnectivityState(serial, NrDualConnectivityState::DISABLE);
+    ASSERT_OK(res);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+    if (getRadioHalCapabilities()) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+                                     {RadioError::REQUEST_NOT_SUPPORTED}));
+    } else {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_network->rspInfo.error,
+                {RadioError::RADIO_NOT_AVAILABLE, RadioError::INTERNAL_ERR,
+                 RadioError::INVALID_STATE, RadioError::REQUEST_NOT_SUPPORTED, RadioError::NONE}));
+    }
+}
+
+/*
+ * Test IRadioNetwork.isNrDualConnectivityEnabled() for the response returned.
+ */
+TEST_P(RadioNetworkTest, isNrDualConnectivityEnabled) {
+    serial = GetRandomSerialNumber();
+
+    ndk::ScopedAStatus res = radio_network->isNrDualConnectivityEnabled(serial);
+    ASSERT_OK(res);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+    if (getRadioHalCapabilities()) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+                                     {RadioError::REQUEST_NOT_SUPPORTED}));
+    } else {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_network->rspInfo.error,
+                {RadioError::RADIO_NOT_AVAILABLE, RadioError::INTERNAL_ERR, RadioError::NONE}));
+    }
+}
+
+void RadioNetworkTest::invokeAndExpectResponse(
+        std::function<ndk::ScopedAStatus(int32_t serial)> request,
+        std::vector<RadioError> errors_to_check) {
+    serial = GetRandomSerialNumber();
+
+    ndk::ScopedAStatus res = request(serial);
+    ASSERT_OK(res);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error, errors_to_check));
+}
+
+/*
+ * Test IRadioNetwork.getUsageSetting()
+ *
+ * Verify that the usage setting can be retrieved.
+ */
+TEST_P(RadioNetworkTest, getUsageSetting) {
+    invokeAndExpectResponse([&](int serial) { return radio_network->getUsageSetting(serial); },
+                            {RadioError::RADIO_NOT_AVAILABLE, RadioError::INVALID_STATE,
+                             RadioError::SIM_ABSENT, RadioError::INTERNAL_ERR, RadioError::NONE});
+
+    ASSERT_TRUE(radioRsp_network->usageSetting == UsageSetting::VOICE_CENTRIC ||
+                radioRsp_network->usageSetting == UsageSetting::DATA_CENTRIC);
+}
+
+void RadioNetworkTest::testSetUsageSetting_InvalidValues(std::vector<RadioError> errors) {
+    invokeAndExpectResponse(
+            [&](int serial) {
+                return radio_network->setUsageSetting(serial,
+                                                      UsageSetting(0) /*below valid range*/);
+            },
+            errors);
+    invokeAndExpectResponse(
+            [&](int serial) {
+                return radio_network->setUsageSetting(serial, UsageSetting(-1) /*negative*/);
+            },
+            errors);
+    invokeAndExpectResponse(
+            [&](int serial) {
+                return radio_network->setUsageSetting(serial,
+                                                      UsageSetting(3) /*above valid range*/);
+            },
+            errors);
+}
+
+/*
+ * Test IRadioNetwork.setUsageSetting() and IRadioNetwork.getUsageSetting()
+ *
+ * Verify the following:
+ * -That the usage setting can be retrieved.
+ * -That the usage setting can be successfully set to allowed values.
+ * -That the usage setting cannot be set to invalid values.
+ */
+TEST_P(RadioNetworkTest, setUsageSetting) {
+    invokeAndExpectResponse([&](int serial) { return radio_network->getUsageSetting(serial); },
+                            {RadioError::RADIO_NOT_AVAILABLE, RadioError::INVALID_STATE,
+                             RadioError::SIM_ABSENT, RadioError::INTERNAL_ERR, RadioError::NONE});
+
+    if (radioRsp_network->rspInfo.error != RadioError::NONE) {
+        // Test only for invalid values, with the only allowable response being the same error
+        // that was previously provided, or an error indicating invalid arguments.
+        testSetUsageSetting_InvalidValues(
+                {radioRsp_network->rspInfo.error, RadioError::INVALID_ARGUMENTS});
+        // It is unsafe to proceed with setting valid values without knowing the starting value, but
+        // we expect errors anyway, so not necessary.
+        return;
+    } else {
+        // Because querying succeeded, the device is in a valid state to test for invalid values
+        // and the only thing that can change is that we expect to have an EINVAL return each time.
+        testSetUsageSetting_InvalidValues({RadioError::INVALID_ARGUMENTS});
+    }
+
+    // Store the original setting value to reset later.
+    const UsageSetting originalSetting = radioRsp_network->usageSetting;
+
+    // Choose the "other" value that is not the current value for test.
+    const UsageSetting testSetting = radioRsp_network->usageSetting == UsageSetting::VOICE_CENTRIC
+                                             ? UsageSetting::DATA_CENTRIC
+                                             : UsageSetting::VOICE_CENTRIC;
+
+    // Set an alternative setting; it may either succeed or be disallowed as out of range for
+    // the current device (if the device only supports its current mode).
+    invokeAndExpectResponse(
+            [&](int serial) { return radio_network->setUsageSetting(serial, testSetting); },
+            {RadioError::INVALID_ARGUMENTS, RadioError::NONE});
+
+    // If there was no error, then we expect the test setting to be set, or if there is an error
+    // we expect the original setting to be maintained.
+    const UsageSetting expectedSetting =
+            radioRsp_network->rspInfo.error == RadioError::NONE ? testSetting : originalSetting;
+    invokeAndExpectResponse([&](int serial) { return radio_network->getUsageSetting(serial); },
+                            {RadioError::NONE});
+
+    const UsageSetting updatedSetting = radioRsp_network->usageSetting;
+
+    // Re-set the original setting, which must always succeed.
+    invokeAndExpectResponse(
+            [&](int serial) { return radio_network->setUsageSetting(serial, originalSetting); },
+            {RadioError::NONE});
+
+    // After resetting the value to its original value, update the local cache, which must
+    // always succeed.
+    invokeAndExpectResponse([&](int serial) { return radio_network->getUsageSetting(serial); },
+                            {RadioError::NONE});
+
+    // Check that indeed the updated setting was set. We do this after resetting to original
+    // conditions to avoid early-exiting the test and leaving the device in a modified state.
+    EXPECT_EQ(expectedSetting, updatedSetting);
+    // Check that indeed the original setting was reset.
+    EXPECT_EQ(originalSetting, radioRsp_network->usageSetting);
+}
+
+/*
+ * Test IRadioNetwork.setSignalStrengthReportingCriteria() with invalid hysteresisDb
+ */
+TEST_P(RadioNetworkTest, setSignalStrengthReportingCriteria_invalidHysteresisDb) {
+    serial = GetRandomSerialNumber();
+
+    SignalThresholdInfo signalThresholdInfo;
+    signalThresholdInfo.signalMeasurement = SignalThresholdInfo::SIGNAL_MEASUREMENT_TYPE_RSSI;
+    signalThresholdInfo.hysteresisMs = 5000;
+    signalThresholdInfo.hysteresisDb = 10;  // hysteresisDb too large given threshold list deltas
+    signalThresholdInfo.thresholds = {-109, -103, -97, -89};
+    signalThresholdInfo.isEnabled = true;
+    signalThresholdInfo.ran = AccessNetwork::GERAN;
+
+    ndk::ScopedAStatus res =
+            radio_network->setSignalStrengthReportingCriteria(serial, {signalThresholdInfo});
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    ALOGI("setSignalStrengthReportingCriteria_invalidHysteresisDb, rspInfo.error = %s\n",
+          toString(radioRsp_network->rspInfo.error).c_str());
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error, {RadioError::INVALID_ARGUMENTS}));
+}
+
+/*
+ * Test IRadioNetwork.setSignalStrengthReportingCriteria() with empty thresholds
+ */
+TEST_P(RadioNetworkTest, setSignalStrengthReportingCriteria_EmptyThresholds) {
+    serial = GetRandomSerialNumber();
+
+    SignalThresholdInfo signalThresholdInfo;
+    signalThresholdInfo.signalMeasurement = SignalThresholdInfo::SIGNAL_MEASUREMENT_TYPE_RSSI;
+    signalThresholdInfo.hysteresisMs = 0;
+    signalThresholdInfo.hysteresisDb = 0;
+    signalThresholdInfo.isEnabled = true;
+    signalThresholdInfo.ran = AccessNetwork::GERAN;
+
+    ndk::ScopedAStatus res =
+            radio_network->setSignalStrengthReportingCriteria(serial, {signalThresholdInfo});
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    ALOGI("setSignalStrengthReportingCriteria_EmptyParams, rspInfo.error = %s\n",
+          toString(radioRsp_network->rspInfo.error).c_str());
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error, {RadioError::NONE}));
+}
+
+/*
+ * Test IRadioNetwork.setSignalStrengthReportingCriteria() for GERAN
+ */
+TEST_P(RadioNetworkTest, setSignalStrengthReportingCriteria_Geran) {
+    serial = GetRandomSerialNumber();
+
+    SignalThresholdInfo signalThresholdInfo;
+    signalThresholdInfo.signalMeasurement = SignalThresholdInfo::SIGNAL_MEASUREMENT_TYPE_RSSI;
+    signalThresholdInfo.hysteresisMs = 5000;
+    signalThresholdInfo.hysteresisDb = 2;
+    signalThresholdInfo.thresholds = {-109, -103, -97, -89};
+    signalThresholdInfo.isEnabled = true;
+    signalThresholdInfo.ran = AccessNetwork::GERAN;
+
+    ndk::ScopedAStatus res =
+            radio_network->setSignalStrengthReportingCriteria(serial, {signalThresholdInfo});
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    ALOGI("setSignalStrengthReportingCriteria_Geran, rspInfo.error = %s\n",
+          toString(radioRsp_network->rspInfo.error).c_str());
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error, {RadioError::NONE}));
+}
+
+/*
+ * Test IRadioNetwork.setSignalStrengthReportingCriteria() for UTRAN
+ */
+TEST_P(RadioNetworkTest, setSignalStrengthReportingCriteria_Utran) {
+    serial = GetRandomSerialNumber();
+
+    SignalThresholdInfo signalThresholdInfo;
+    signalThresholdInfo.signalMeasurement = SignalThresholdInfo::SIGNAL_MEASUREMENT_TYPE_RSCP;
+    signalThresholdInfo.hysteresisMs = 5000;
+    signalThresholdInfo.hysteresisDb = 2;
+    signalThresholdInfo.thresholds = {-110, -97, -73, -49, -25};
+    signalThresholdInfo.isEnabled = true;
+    signalThresholdInfo.ran = AccessNetwork::UTRAN;
+
+    ndk::ScopedAStatus res =
+            radio_network->setSignalStrengthReportingCriteria(serial, {signalThresholdInfo});
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    ALOGI("setSignalStrengthReportingCriteria_Utran, rspInfo.error = %s\n",
+          toString(radioRsp_network->rspInfo.error).c_str());
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error, {RadioError::NONE}));
+}
+
+/*
+ * Test IRadioNetwork.setSignalStrengthReportingCriteria() for EUTRAN
+ */
+TEST_P(RadioNetworkTest, setSignalStrengthReportingCriteria_Eutran_RSRP) {
+    serial = GetRandomSerialNumber();
+
+    SignalThresholdInfo signalThresholdInfo;
+    signalThresholdInfo.signalMeasurement = SignalThresholdInfo::SIGNAL_MEASUREMENT_TYPE_RSRP;
+    signalThresholdInfo.hysteresisMs = 5000;
+    signalThresholdInfo.hysteresisDb = 2;
+    signalThresholdInfo.thresholds = {-128, -108, -88, -68};
+    signalThresholdInfo.isEnabled = true;
+    signalThresholdInfo.ran = AccessNetwork::EUTRAN;
+
+    ndk::ScopedAStatus res =
+            radio_network->setSignalStrengthReportingCriteria(serial, {signalThresholdInfo});
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    ALOGI("setSignalStrengthReportingCriteria_Eutran, rspInfo.error = %s\n",
+          toString(radioRsp_network->rspInfo.error).c_str());
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error, {RadioError::NONE}));
+}
+
+/*
+ * Test IRadioNetwork.setSignalStrengthReportingCriteria() for EUTRAN
+ */
+TEST_P(RadioNetworkTest, setSignalStrengthReportingCriteria_Eutran_RSRQ) {
+    serial = GetRandomSerialNumber();
+
+    SignalThresholdInfo signalThresholdInfo;
+    signalThresholdInfo.signalMeasurement = SignalThresholdInfo::SIGNAL_MEASUREMENT_TYPE_RSRQ;
+    signalThresholdInfo.hysteresisMs = 5000;
+    signalThresholdInfo.hysteresisDb = 2;
+    signalThresholdInfo.thresholds = {-27, -20, -13, -6};
+    signalThresholdInfo.isEnabled = true;
+    signalThresholdInfo.ran = AccessNetwork::EUTRAN;
+
+    ndk::ScopedAStatus res =
+            radio_network->setSignalStrengthReportingCriteria(serial, {signalThresholdInfo});
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    ALOGI("setSignalStrengthReportingCriteria_Eutran, rspInfo.error = %s\n",
+          toString(radioRsp_network->rspInfo.error).c_str());
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error, {RadioError::NONE}));
+}
+
+/*
+ * Test IRadioNetwork.setSignalStrengthReportingCriteria() for EUTRAN
+ */
+TEST_P(RadioNetworkTest, setSignalStrengthReportingCriteria_Eutran_RSSNR) {
+    serial = GetRandomSerialNumber();
+
+    SignalThresholdInfo signalThresholdInfo;
+    signalThresholdInfo.signalMeasurement = SignalThresholdInfo::SIGNAL_MEASUREMENT_TYPE_RSSNR;
+    signalThresholdInfo.hysteresisMs = 5000;
+    signalThresholdInfo.hysteresisDb = 2;
+    signalThresholdInfo.thresholds = {-10, 0, 10, 20};
+    signalThresholdInfo.isEnabled = true;
+    signalThresholdInfo.ran = AccessNetwork::EUTRAN;
+
+    ndk::ScopedAStatus res =
+            radio_network->setSignalStrengthReportingCriteria(serial, {signalThresholdInfo});
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+}
+
+/*
+ * Test IRadioNetwork.setSignalStrengthReportingCriteria() for CDMA2000
+ */
+TEST_P(RadioNetworkTest, setSignalStrengthReportingCriteria_Cdma2000) {
+    serial = GetRandomSerialNumber();
+
+    SignalThresholdInfo signalThresholdInfo;
+    signalThresholdInfo.signalMeasurement = SignalThresholdInfo::SIGNAL_MEASUREMENT_TYPE_RSSI;
+    signalThresholdInfo.hysteresisMs = 5000;
+    signalThresholdInfo.hysteresisDb = 2;
+    signalThresholdInfo.thresholds = {-105, -90, -75, -65};
+    signalThresholdInfo.isEnabled = true;
+    signalThresholdInfo.ran = AccessNetwork::CDMA2000;
+
+    ndk::ScopedAStatus res =
+            radio_network->setSignalStrengthReportingCriteria(serial, {signalThresholdInfo});
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    ALOGI("setSignalStrengthReportingCriteria_Cdma2000, rspInfo.error = %s\n",
+          toString(radioRsp_network->rspInfo.error).c_str());
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error, {RadioError::NONE}));
+}
+
+/*
+ * Test IRadioNetwork.setSignalStrengthReportingCriteria() for NGRAN_SSRSRP
+ */
+TEST_P(RadioNetworkTest, setSignalStrengthReportingCriteria_NGRAN_SSRSRP) {
+    serial = GetRandomSerialNumber();
+
+    SignalThresholdInfo signalThresholdInfo;
+    signalThresholdInfo.signalMeasurement = SignalThresholdInfo::SIGNAL_MEASUREMENT_TYPE_SSRSRP;
+    signalThresholdInfo.hysteresisMs = 5000;
+    signalThresholdInfo.hysteresisDb = 0;
+    signalThresholdInfo.thresholds = {-105, -90, -75, -65};
+    signalThresholdInfo.isEnabled = true;
+    signalThresholdInfo.ran = AccessNetwork::NGRAN;
+
+    ndk::ScopedAStatus res =
+            radio_network->setSignalStrengthReportingCriteria(serial, {signalThresholdInfo});
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    ALOGI("setSignalStrengthReportingCriteria_NGRAN_SSRSRP, rspInfo.error = %s\n",
+          toString(radioRsp_network->rspInfo.error).c_str());
+
+    // Allow REQUEST_NOT_SUPPORTED because some non-5G device may not support NGRAN for
+    // setSignalStrengthReportingCriteria()
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+                                 {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+}
+
+/*
+ * Test IRadioNetwork.setSignalStrengthReportingCriteria() for NGRAN_SSRSRQ
+ */
+TEST_P(RadioNetworkTest, setSignalStrengthReportingCriteria_NGRAN_SSRSRQ) {
+    serial = GetRandomSerialNumber();
+
+    SignalThresholdInfo signalThresholdInfo;
+    signalThresholdInfo.signalMeasurement = SignalThresholdInfo::SIGNAL_MEASUREMENT_TYPE_SSRSRQ;
+    signalThresholdInfo.hysteresisMs = 5000;
+    signalThresholdInfo.hysteresisDb = 0;
+    signalThresholdInfo.thresholds = {-43, -20, 0, 20};
+    signalThresholdInfo.isEnabled = true;
+    signalThresholdInfo.ran = AccessNetwork::NGRAN;
+
+    ndk::ScopedAStatus res =
+            radio_network->setSignalStrengthReportingCriteria(serial, {signalThresholdInfo});
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    ALOGI("setSignalStrengthReportingCriteria_NGRAN_SSRSRQ, rspInfo.error = %s\n",
+          toString(radioRsp_network->rspInfo.error).c_str());
+
+    // Allow REQUEST_NOT_SUPPORTED because some non-5G device may not support NGRAN for
+    // setSignalStrengthReportingCriteria()
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+                                 {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+}
+
+/*
+ * Test IRadioNetwork.setSignalStrengthReportingCriteria() for EUTRAN
+ */
+TEST_P(RadioNetworkTest, setSignalStrengthReportingCriteria_Disable_RSSNR) {
+    serial = GetRandomSerialNumber();
+
+    SignalThresholdInfo signalThresholdInfo;
+    signalThresholdInfo.signalMeasurement = SignalThresholdInfo::SIGNAL_MEASUREMENT_TYPE_RSSNR;
+    signalThresholdInfo.hysteresisMs = 5000;
+    signalThresholdInfo.hysteresisDb = 2;
+    signalThresholdInfo.thresholds = {-10, 0, 10, 20};
+    signalThresholdInfo.isEnabled = false;
+    signalThresholdInfo.ran = AccessNetwork::EUTRAN;
+
+    ndk::ScopedAStatus res =
+            radio_network->setSignalStrengthReportingCriteria(serial, {signalThresholdInfo});
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+}
+
+/*
+ * Test IRadioNetwork.setSignalStrengthReportingCriteria() for NGRAN_SSSINR
+ */
+TEST_P(RadioNetworkTest, setSignalStrengthReportingCriteria_NGRAN_SSSINR) {
+    serial = GetRandomSerialNumber();
+
+    SignalThresholdInfo signalThresholdInfo;
+    signalThresholdInfo.signalMeasurement = SignalThresholdInfo::SIGNAL_MEASUREMENT_TYPE_SSSINR;
+    signalThresholdInfo.hysteresisMs = 5000;
+    signalThresholdInfo.hysteresisDb = 0;
+    signalThresholdInfo.thresholds = {-10, 3, 16, 18};
+    signalThresholdInfo.isEnabled = true;
+    signalThresholdInfo.ran = AccessNetwork::NGRAN;
+
+    ndk::ScopedAStatus res =
+            radio_network->setSignalStrengthReportingCriteria(serial, {signalThresholdInfo});
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    ALOGI("setSignalStrengthReportingCriteria_NGRAN_SSSINR, rspInfo.error = %s\n",
+          toString(radioRsp_network->rspInfo.error).c_str());
+
+    // Allow REQUEST_NOT_SUPPORTED because some non-5G device may not support NGRAN for
+    // setSignalStrengthReportingCriteria()
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+                                 {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+}
+
+/*
+ * Test IRadioNetwork.setSignalStrengthReportingCriteria() for multi-RANs per request
+ */
+TEST_P(RadioNetworkTest, setSignalStrengthReportingCriteria_multiRansPerRequest) {
+    SignalThresholdInfo signalThresholdInfoGeran;
+    signalThresholdInfoGeran.signalMeasurement = SignalThresholdInfo::SIGNAL_MEASUREMENT_TYPE_RSSI;
+    signalThresholdInfoGeran.hysteresisMs = 5000;
+    signalThresholdInfoGeran.hysteresisDb = 2;
+    signalThresholdInfoGeran.thresholds = {-109, -103, -97, -89};
+    signalThresholdInfoGeran.isEnabled = true;
+    signalThresholdInfoGeran.ran = AccessNetwork::GERAN;
+
+    SignalThresholdInfo signalThresholdInfoUtran;
+    signalThresholdInfoUtran.signalMeasurement = SignalThresholdInfo::SIGNAL_MEASUREMENT_TYPE_RSCP;
+    signalThresholdInfoUtran.hysteresisMs = 5000;
+    signalThresholdInfoUtran.hysteresisDb = 2;
+    signalThresholdInfoUtran.thresholds = {-110, -97, -73, -49, -25};
+    signalThresholdInfoUtran.isEnabled = true;
+    signalThresholdInfoUtran.ran = AccessNetwork::UTRAN;
+
+    SignalThresholdInfo signalThresholdInfoEutran;
+    signalThresholdInfoEutran.signalMeasurement = SignalThresholdInfo::SIGNAL_MEASUREMENT_TYPE_RSRP;
+    signalThresholdInfoEutran.hysteresisMs = 5000;
+    signalThresholdInfoEutran.hysteresisDb = 2;
+    signalThresholdInfoEutran.thresholds = {-128, -108, -88, -68};
+    signalThresholdInfoEutran.isEnabled = true;
+    signalThresholdInfoEutran.ran = AccessNetwork::EUTRAN;
+
+    SignalThresholdInfo signalThresholdInfoCdma2000;
+    signalThresholdInfoCdma2000.signalMeasurement =
+            SignalThresholdInfo::SIGNAL_MEASUREMENT_TYPE_RSSI;
+    signalThresholdInfoCdma2000.hysteresisMs = 5000;
+    signalThresholdInfoCdma2000.hysteresisDb = 2;
+    signalThresholdInfoCdma2000.thresholds = {-105, -90, -75, -65};
+    signalThresholdInfoCdma2000.isEnabled = true;
+    signalThresholdInfoCdma2000.ran = AccessNetwork::CDMA2000;
+
+    SignalThresholdInfo signalThresholdInfoNgran;
+    signalThresholdInfoNgran.signalMeasurement =
+            SignalThresholdInfo::SIGNAL_MEASUREMENT_TYPE_SSRSRP;
+    signalThresholdInfoNgran.hysteresisMs = 5000;
+    signalThresholdInfoNgran.hysteresisDb = 0;
+    signalThresholdInfoNgran.thresholds = {-105, -90, -75, -65};
+    signalThresholdInfoNgran.isEnabled = true;
+    signalThresholdInfoNgran.ran = AccessNetwork::NGRAN;
+
+    const static std::vector<SignalThresholdInfo> candidateSignalThresholdInfos = {
+            signalThresholdInfoGeran, signalThresholdInfoUtran, signalThresholdInfoEutran,
+            signalThresholdInfoCdma2000, signalThresholdInfoNgran};
+
+    std::vector<SignalThresholdInfo> supportedSignalThresholdInfos;
+    for (size_t i = 0; i < candidateSignalThresholdInfos.size(); i++) {
+        serial = GetRandomSerialNumber();
+        ndk::ScopedAStatus res = radio_network->setSignalStrengthReportingCriteria(
+                serial, {candidateSignalThresholdInfos[i]});
+        ASSERT_OK(res);
+        EXPECT_EQ(std::cv_status::no_timeout, wait());
+        if (radioRsp_network->rspInfo.error == RadioError::NONE) {
+            supportedSignalThresholdInfos.push_back(signalThresholdInfoGeran);
+        } else {
+            // Refer to IRadioNetworkResponse#setSignalStrengthReportingCriteriaResponse
+            ASSERT_TRUE(CheckAnyOfErrors(
+                    radioRsp_network->rspInfo.error,
+                    {RadioError::INVALID_ARGUMENTS, RadioError::RADIO_NOT_AVAILABLE}));
+        }
+    }
+
+    ASSERT_FALSE(supportedSignalThresholdInfos.empty());
+
+    serial = GetRandomSerialNumber();
+    ndk::ScopedAStatus res = radio_network->setSignalStrengthReportingCriteria(
+            serial, supportedSignalThresholdInfos);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    ALOGI("setSignalStrengthReportingCriteria_multiRansPerRequest, rspInfo.error = %s\n",
+          toString(radioRsp_network->rspInfo.error).c_str());
+
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error, {RadioError::NONE}));
+}
+
+/*
+ * Test IRadioNetwork.setLinkCapacityReportingCriteria() invalid hysteresisDlKbps
+ */
+TEST_P(RadioNetworkTest, setLinkCapacityReportingCriteria_invalidHysteresisDlKbps) {
+    serial = GetRandomSerialNumber();
+
+    ndk::ScopedAStatus res = radio_network->setLinkCapacityReportingCriteria(
+            serial, 5000,
+            5000,  // hysteresisDlKbps too big for thresholds delta
+            100, {1000, 5000, 10000, 20000}, {500, 1000, 5000, 10000}, AccessNetwork::GERAN);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    ALOGI("setLinkCapacityReportingCriteria_invalidHysteresisDlKbps, rspInfo.error = %s\n",
+          toString(radioRsp_network->rspInfo.error).c_str());
+    // Allow REQUEST_NOT_SUPPORTED as setLinkCapacityReportingCriteria() may not be supported
+    // for GERAN
+    ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+                             {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+}
+
+/*
+ * Test IRadioNetwork.setLinkCapacityReportingCriteria() invalid hysteresisUlKbps
+ */
+TEST_P(RadioNetworkTest, setLinkCapacityReportingCriteria_invalidHysteresisUlKbps) {
+    serial = GetRandomSerialNumber();
+
+    ndk::ScopedAStatus res = radio_network->setLinkCapacityReportingCriteria(
+            serial, 5000, 500, 1000,  // hysteresisUlKbps too big for thresholds delta
+            {1000, 5000, 10000, 20000}, {500, 1000, 5000, 10000}, AccessNetwork::GERAN);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    ALOGI("setLinkCapacityReportingCriteria_invalidHysteresisUlKbps, rspInfo.error = %s\n",
+          toString(radioRsp_network->rspInfo.error).c_str());
+    // Allow REQUEST_NOT_SUPPORTED as setLinkCapacityReportingCriteria() may not be supported
+    // for GERAN
+    ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+                             {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+}
+
+/*
+ * Test IRadioNetwork.setLinkCapacityReportingCriteria() empty params
+ */
+TEST_P(RadioNetworkTest, setLinkCapacityReportingCriteria_emptyParams) {
+    serial = GetRandomSerialNumber();
+
+    ndk::ScopedAStatus res = radio_network->setLinkCapacityReportingCriteria(
+            serial, 0, 0, 0, {}, {}, AccessNetwork::GERAN);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    ALOGI("setLinkCapacityReportingCriteria_emptyParams, rspInfo.error = %s\n",
+          toString(radioRsp_network->rspInfo.error).c_str());
+    // Allow REQUEST_NOT_SUPPORTED as setLinkCapacityReportingCriteria() may not be supported
+    // for GERAN
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+                                 {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+}
+
+/*
+ * Test IRadioNetwork.setLinkCapacityReportingCriteria() for GERAN
+ */
+TEST_P(RadioNetworkTest, setLinkCapacityReportingCriteria_Geran) {
+    serial = GetRandomSerialNumber();
+
+    ndk::ScopedAStatus res = radio_network->setLinkCapacityReportingCriteria(
+            serial, 5000, 500, 100, {1000, 5000, 10000, 20000}, {500, 1000, 5000, 10000},
+            AccessNetwork::GERAN);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    ALOGI("setLinkCapacityReportingCriteria_Geran, rspInfo.error = %s\n",
+          toString(radioRsp_network->rspInfo.error).c_str());
+    // Allow REQUEST_NOT_SUPPORTED as setLinkCapacityReportingCriteria() may not be supported
+    // for GERAN
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+                                 {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+}
+
+/*
+ * Test IRadioNetwork.setSystemSelectionChannels() for the response returned.
+ */
+TEST_P(RadioNetworkTest, setSystemSelectionChannels) {
+    serial = GetRandomSerialNumber();
+
+    RadioAccessSpecifierBands bandP900 =
+            RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+                    {GeranBands::BAND_P900});
+    RadioAccessSpecifierBands band850 =
+            RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+                    {GeranBands::BAND_850});
+    RadioAccessSpecifier specifierP900 = {
+            .accessNetwork = AccessNetwork::GERAN, .bands = bandP900, .channels = {1, 2}};
+    RadioAccessSpecifier specifier850 = {
+            .accessNetwork = AccessNetwork::GERAN, .bands = band850, .channels = {128, 129}};
+
+    ndk::ScopedAStatus res =
+            radio_network->setSystemSelectionChannels(serial, true, {specifierP900, specifier850});
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+    ALOGI("setSystemSelectionChannels, rspInfo.error = %s\n",
+          toString(radioRsp_network->rspInfo.error).c_str());
+    ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp_network->rspInfo.error,
+            {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::INTERNAL_ERR}));
+
+    if (radioRsp_network->rspInfo.error == RadioError::NONE) {
+        serial = GetRandomSerialNumber();
+        ndk::ScopedAStatus res = radio_network->setSystemSelectionChannels(
+                serial, false, {specifierP900, specifier850});
+        ASSERT_OK(res);
+        EXPECT_EQ(std::cv_status::no_timeout, wait());
+        EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+        EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+        ALOGI("setSystemSelectionChannels, rspInfo.error = %s\n",
+              toString(radioRsp_network->rspInfo.error).c_str());
+        EXPECT_EQ(RadioError::NONE, radioRsp_network->rspInfo.error);
+    }
+}
+
+/*
+ * Test IRadioNetwork.startNetworkScan() for the response returned.
+ */
+TEST_P(RadioNetworkTest, startNetworkScan) {
+    serial = GetRandomSerialNumber();
+
+    RadioAccessSpecifierBands bandP900 =
+            RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+                    {GeranBands::BAND_P900});
+    RadioAccessSpecifierBands band850 =
+            RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+                    {GeranBands::BAND_850});
+    RadioAccessSpecifier specifierP900 = {
+            .accessNetwork = AccessNetwork::GERAN, .bands = bandP900, .channels = {1, 2}};
+    RadioAccessSpecifier specifier850 = {
+            .accessNetwork = AccessNetwork::GERAN, .bands = band850, .channels = {128, 129}};
+
+    NetworkScanRequest request = {.type = NetworkScanRequest::SCAN_TYPE_ONE_SHOT,
+                                  .interval = 60,
+                                  .specifiers = {specifierP900, specifier850},
+                                  .maxSearchTime = 60,
+                                  .incrementalResults = false,
+                                  .incrementalResultsPeriodicity = 1};
+
+    ndk::ScopedAStatus res = radio_network->startNetworkScan(serial, request);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+    ALOGI("startNetworkScan, rspInfo.error = %s\n",
+          toString(radioRsp_network->rspInfo.error).c_str());
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error, {RadioError::SIM_ABSENT}));
+    } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+        // OPERATION_NOT_ALLOWED should not be allowed; however, some vendors do
+        // not support the required manual GSM search functionality. This is
+        // tracked in b/112206766. Modems have "GSM" rat scan need to
+        // support scanning requests combined with some parameters.
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+                                     {RadioError::NONE, RadioError::OPERATION_NOT_ALLOWED}));
+    }
+
+    if (radioRsp_network->rspInfo.error == RadioError::NONE) {
+        ALOGI("Stop Network Scan");
+        stopNetworkScan();
+    }
+}
+
+/*
+ * Test IRadioNetwork.startNetworkScan() with invalid specifier.
+ */
+TEST_P(RadioNetworkTest, startNetworkScan_InvalidArgument) {
+    serial = GetRandomSerialNumber();
+
+    NetworkScanRequest request = {.type = NetworkScanRequest::SCAN_TYPE_ONE_SHOT, .interval = 60};
+
+    ndk::ScopedAStatus res = radio_network->startNetworkScan(serial, request);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+    ALOGI("startNetworkScan_InvalidArgument, rspInfo.error = %s\n",
+          toString(radioRsp_network->rspInfo.error).c_str());
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+                                     {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
+    } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_network->rspInfo.error,
+                {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+    }
+}
+
+/*
+ * Test IRadioNetwork.startNetworkScan() with invalid interval (lower boundary).
+ */
+TEST_P(RadioNetworkTest, startNetworkScan_InvalidInterval1) {
+    serial = GetRandomSerialNumber();
+
+    RadioAccessSpecifierBands bandP900 =
+            RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+                    {GeranBands::BAND_P900});
+    RadioAccessSpecifierBands band850 =
+            RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+                    {GeranBands::BAND_850});
+    RadioAccessSpecifier specifierP900 = {
+            .accessNetwork = AccessNetwork::GERAN, .bands = bandP900, .channels = {1, 2}};
+    RadioAccessSpecifier specifier850 = {
+            .accessNetwork = AccessNetwork::GERAN, .bands = band850, .channels = {128, 129}};
+
+    NetworkScanRequest request = {.type = NetworkScanRequest::SCAN_TYPE_ONE_SHOT,
+                                  .interval = 4,
+                                  .specifiers = {specifierP900, specifier850},
+                                  .maxSearchTime = 60,
+                                  .incrementalResults = false,
+                                  .incrementalResultsPeriodicity = 1};
+
+    ndk::ScopedAStatus res = radio_network->startNetworkScan(serial, request);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+    ALOGI("startNetworkScan_InvalidInterval1, rspInfo.error = %s\n",
+          toString(radioRsp_network->rspInfo.error).c_str());
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+                                     {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
+    } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_network->rspInfo.error,
+                {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+    }
+}
+
+/*
+ * Test IRadioNetwork.startNetworkScan() with invalid interval (upper boundary).
+ */
+TEST_P(RadioNetworkTest, startNetworkScan_InvalidInterval2) {
+    serial = GetRandomSerialNumber();
+
+    RadioAccessSpecifierBands bandP900 =
+            RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+                    {GeranBands::BAND_P900});
+    RadioAccessSpecifierBands band850 =
+            RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+                    {GeranBands::BAND_850});
+    RadioAccessSpecifier specifierP900 = {
+            .accessNetwork = AccessNetwork::GERAN, .bands = bandP900, .channels = {1, 2}};
+    RadioAccessSpecifier specifier850 = {
+            .accessNetwork = AccessNetwork::GERAN, .bands = band850, .channels = {128, 129}};
+
+    NetworkScanRequest request = {.type = NetworkScanRequest::SCAN_TYPE_ONE_SHOT,
+                                  .interval = 301,
+                                  .specifiers = {specifierP900, specifier850},
+                                  .maxSearchTime = 60,
+                                  .incrementalResults = false,
+                                  .incrementalResultsPeriodicity = 1};
+
+    ndk::ScopedAStatus res = radio_network->startNetworkScan(serial, request);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+    ALOGI("startNetworkScan_InvalidInterval2, rspInfo.error = %s\n",
+          toString(radioRsp_network->rspInfo.error).c_str());
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+                                     {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
+    } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_network->rspInfo.error,
+                {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+    }
+}
+
+/*
+ * Test IRadioNetwork.startNetworkScan() with invalid max search time (lower boundary).
+ */
+TEST_P(RadioNetworkTest, startNetworkScan_InvalidMaxSearchTime1) {
+    serial = GetRandomSerialNumber();
+
+    RadioAccessSpecifierBands bandP900 =
+            RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+                    {GeranBands::BAND_P900});
+    RadioAccessSpecifierBands band850 =
+            RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+                    {GeranBands::BAND_850});
+    RadioAccessSpecifier specifierP900 = {
+            .accessNetwork = AccessNetwork::GERAN, .bands = bandP900, .channels = {1, 2}};
+    RadioAccessSpecifier specifier850 = {
+            .accessNetwork = AccessNetwork::GERAN, .bands = band850, .channels = {128, 129}};
+
+    NetworkScanRequest request = {.type = NetworkScanRequest::SCAN_TYPE_ONE_SHOT,
+                                  .interval = 60,
+                                  .specifiers = {specifierP900, specifier850},
+                                  .maxSearchTime = 59,
+                                  .incrementalResults = false,
+                                  .incrementalResultsPeriodicity = 1};
+
+    ndk::ScopedAStatus res = radio_network->startNetworkScan(serial, request);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+    ALOGI("startNetworkScan_InvalidMaxSearchTime1, rspInfo.error = %s\n",
+          toString(radioRsp_network->rspInfo.error).c_str());
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+                                     {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
+    } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_network->rspInfo.error,
+                {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+    }
+}
+
+/*
+ * Test IRadioNetwork.startNetworkScan() with invalid max search time (upper boundary).
+ */
+TEST_P(RadioNetworkTest, startNetworkScan_InvalidMaxSearchTime2) {
+    serial = GetRandomSerialNumber();
+
+    RadioAccessSpecifierBands bandP900 =
+            RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+                    {GeranBands::BAND_P900});
+    RadioAccessSpecifierBands band850 =
+            RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+                    {GeranBands::BAND_850});
+    RadioAccessSpecifier specifierP900 = {
+            .accessNetwork = AccessNetwork::GERAN, .bands = bandP900, .channels = {1, 2}};
+    RadioAccessSpecifier specifier850 = {
+            .accessNetwork = AccessNetwork::GERAN, .bands = band850, .channels = {128, 129}};
+
+    NetworkScanRequest request = {.type = NetworkScanRequest::SCAN_TYPE_ONE_SHOT,
+                                  .interval = 60,
+                                  .specifiers = {specifierP900, specifier850},
+                                  .maxSearchTime = 3601,
+                                  .incrementalResults = false,
+                                  .incrementalResultsPeriodicity = 1};
+
+    ndk::ScopedAStatus res = radio_network->startNetworkScan(serial, request);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+    ALOGI("startNetworkScan_InvalidMaxSearchTime2, rspInfo.error = %s\n",
+          toString(radioRsp_network->rspInfo.error).c_str());
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+                                     {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
+    } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_network->rspInfo.error,
+                {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+    }
+}
+
+/*
+ * Test IRadioNetwork.startNetworkScan() with invalid periodicity (lower boundary).
+ */
+TEST_P(RadioNetworkTest, startNetworkScan_InvalidPeriodicity1) {
+    serial = GetRandomSerialNumber();
+
+    RadioAccessSpecifierBands bandP900 =
+            RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+                    {GeranBands::BAND_P900});
+    RadioAccessSpecifierBands band850 =
+            RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+                    {GeranBands::BAND_850});
+    RadioAccessSpecifier specifierP900 = {
+            .accessNetwork = AccessNetwork::GERAN, .bands = bandP900, .channels = {1, 2}};
+    RadioAccessSpecifier specifier850 = {
+            .accessNetwork = AccessNetwork::GERAN, .bands = band850, .channels = {128, 129}};
+
+    NetworkScanRequest request = {.type = NetworkScanRequest::SCAN_TYPE_ONE_SHOT,
+                                  .interval = 60,
+                                  .specifiers = {specifierP900, specifier850},
+                                  .maxSearchTime = 600,
+                                  .incrementalResults = true,
+                                  .incrementalResultsPeriodicity = 0};
+
+    ndk::ScopedAStatus res = radio_network->startNetworkScan(serial, request);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+    ALOGI("startNetworkScan_InvalidPeriodicity1, rspInfo.error = %s\n",
+          toString(radioRsp_network->rspInfo.error).c_str());
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+                                     {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
+    } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_network->rspInfo.error,
+                {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+    }
+}
+
+/*
+ * Test IRadioNetwork.startNetworkScan() with invalid periodicity (upper boundary).
+ */
+TEST_P(RadioNetworkTest, startNetworkScan_InvalidPeriodicity2) {
+    serial = GetRandomSerialNumber();
+
+    RadioAccessSpecifierBands bandP900 =
+            RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+                    {GeranBands::BAND_P900});
+    RadioAccessSpecifierBands band850 =
+            RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+                    {GeranBands::BAND_850});
+    RadioAccessSpecifier specifierP900 = {
+            .accessNetwork = AccessNetwork::GERAN, .bands = bandP900, .channels = {1, 2}};
+    RadioAccessSpecifier specifier850 = {
+            .accessNetwork = AccessNetwork::GERAN, .bands = band850, .channels = {128, 129}};
+
+    NetworkScanRequest request = {.type = NetworkScanRequest::SCAN_TYPE_ONE_SHOT,
+                                  .interval = 60,
+                                  .specifiers = {specifierP900, specifier850},
+                                  .maxSearchTime = 600,
+                                  .incrementalResults = true,
+                                  .incrementalResultsPeriodicity = 11};
+
+    ndk::ScopedAStatus res = radio_network->startNetworkScan(serial, request);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+    ALOGI("startNetworkScan_InvalidPeriodicity2, rspInfo.error = %s\n",
+          toString(radioRsp_network->rspInfo.error).c_str());
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+                                     {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
+    } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_network->rspInfo.error,
+                {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+    }
+}
+
+/*
+ * Test IRadioNetwork.startNetworkScan() with valid periodicity
+ */
+TEST_P(RadioNetworkTest, startNetworkScan_GoodRequest1) {
+    serial = GetRandomSerialNumber();
+
+    RadioAccessSpecifierBands bandP900 =
+            RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+                    {GeranBands::BAND_P900});
+    RadioAccessSpecifierBands band850 =
+            RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+                    {GeranBands::BAND_850});
+    RadioAccessSpecifier specifierP900 = {
+            .accessNetwork = AccessNetwork::GERAN, .bands = bandP900, .channels = {1, 2}};
+    RadioAccessSpecifier specifier850 = {
+            .accessNetwork = AccessNetwork::GERAN, .bands = band850, .channels = {128, 129}};
+
+    NetworkScanRequest request = {.type = NetworkScanRequest::SCAN_TYPE_ONE_SHOT,
+                                  .interval = 60,
+                                  .specifiers = {specifierP900, specifier850},
+                                  .maxSearchTime = 360,
+                                  .incrementalResults = false,
+                                  .incrementalResultsPeriodicity = 10};
+
+    ndk::ScopedAStatus res = radio_network->startNetworkScan(serial, request);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+    ALOGI("startNetworkScan_GoodRequest1, rspInfo.error = %s\n",
+          toString(radioRsp_network->rspInfo.error).c_str());
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+                                     {RadioError::NONE, RadioError::SIM_ABSENT}));
+    } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+                                     {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
+                                      RadioError::REQUEST_NOT_SUPPORTED}));
+    }
+
+    if (radioRsp_network->rspInfo.error == RadioError::NONE) {
+        ALOGI("Stop Network Scan");
+        stopNetworkScan();
+    }
+}
+
+/*
+ * Test IRadioNetwork.startNetworkScan() with valid periodicity and plmns
+ */
+TEST_P(RadioNetworkTest, startNetworkScan_GoodRequest2) {
+    serial = GetRandomSerialNumber();
+
+    RadioAccessSpecifierBands bandP900 =
+            RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+                    {GeranBands::BAND_P900});
+    RadioAccessSpecifierBands band850 =
+            RadioAccessSpecifierBands::make<RadioAccessSpecifierBands::geranBands>(
+                    {GeranBands::BAND_850});
+    RadioAccessSpecifier specifierP900 = {
+            .accessNetwork = AccessNetwork::GERAN, .bands = bandP900, .channels = {1, 2}};
+    RadioAccessSpecifier specifier850 = {
+            .accessNetwork = AccessNetwork::GERAN, .bands = band850, .channels = {128, 129}};
+
+    NetworkScanRequest request = {.type = NetworkScanRequest::SCAN_TYPE_ONE_SHOT,
+                                  .interval = 60,
+                                  .specifiers = {specifierP900, specifier850},
+                                  .maxSearchTime = 360,
+                                  .incrementalResults = false,
+                                  .incrementalResultsPeriodicity = 10,
+                                  .mccMncs = {"310410"}};
+
+    ndk::ScopedAStatus res = radio_network->startNetworkScan(serial, request);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+    ALOGI("startNetworkScan_GoodRequest2, rspInfo.error = %s\n",
+          toString(radioRsp_network->rspInfo.error).c_str());
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+                                     {RadioError::NONE, RadioError::SIM_ABSENT}));
+    } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+                                     {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
+                                      RadioError::REQUEST_NOT_SUPPORTED}));
+    }
+
+    if (radioRsp_network->rspInfo.error == RadioError::NONE) {
+        ALOGI("Stop Network Scan");
+        stopNetworkScan();
+    }
+}
+
+/*
+ * Test IRadioNetwork.setNetworkSelectionModeManual() for the response returned.
+ */
+TEST_P(RadioNetworkTest, setNetworkSelectionModeManual) {
+    serial = GetRandomSerialNumber();
+
+    // can't camp on nonexistent MCCMNC, so we expect this to fail.
+    ndk::ScopedAStatus res =
+            radio_network->setNetworkSelectionModeManual(serial, "123456", AccessNetwork::GERAN);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+                                     {RadioError::NONE, RadioError::ILLEGAL_SIM_OR_ME,
+                                      RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE},
+                                     CHECK_GENERAL_ERROR));
+    } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+                                     {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
+                                      RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE},
+                                     CHECK_GENERAL_ERROR));
+    }
+}
+
+/*
+ * Test IRadioNetwork.getBarringInfo() for the response returned.
+ */
+TEST_P(RadioNetworkTest, getBarringInfo) {
+    serial = GetRandomSerialNumber();
+    ndk::ScopedAStatus res = radio_network->getBarringInfo(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+    ASSERT_TRUE(radioRsp_network->barringInfoList.size() > 0);
+
+    std::set<int> reportedServices;
+
+    // validate that the service types are in range
+    for (const auto& info : radioRsp_network->barringInfoList) {
+        ASSERT_TRUE((info.serviceType >= BarringInfo::SERVICE_TYPE_CS_SERVICE &&
+                     info.serviceType <= BarringInfo::SERVICE_TYPE_SMS) ||
+                    (info.serviceType >= BarringInfo::SERVICE_TYPE_OPERATOR_1 &&
+                     info.serviceType <= BarringInfo::SERVICE_TYPE_OPERATOR_32));
+        reportedServices.insert(info.serviceType);
+
+        // Any type that is "conditional" must have valid values for conditional barring
+        // factor and time.
+        switch (info.barringType) {
+            case BarringInfo::BARRING_TYPE_NONE:  // fall through
+            case BarringInfo::BARRING_TYPE_UNCONDITIONAL:
+                break;
+            case BarringInfo::BARRING_TYPE_CONDITIONAL: {
+                const int32_t barringFactor = info.barringTypeSpecificInfo->factor;
+                ASSERT_TRUE(barringFactor >= 0 && barringFactor <= 100);
+                ASSERT_TRUE(info.barringTypeSpecificInfo->timeSeconds > 0);
+                break;
+            }
+            default:
+                FAIL();
+        }
+    }
+
+    // Certain types of barring are relevant for certain RANs. Ensure that only the right
+    // types are reported. Note that no types are required, simply that for a given technology
+    // only certain types are valid. This is one way to check that implementations are
+    // not providing information that they don't have.
+    static const std::set<int> UTRA_SERVICES{
+            BarringInfo::SERVICE_TYPE_CS_SERVICE, BarringInfo::SERVICE_TYPE_PS_SERVICE,
+            BarringInfo::SERVICE_TYPE_CS_VOICE,   BarringInfo::SERVICE_TYPE_EMERGENCY,
+            BarringInfo::SERVICE_TYPE_SMS,
+    };
+
+    static const std::set<int> EUTRA_SERVICES{
+            BarringInfo::SERVICE_TYPE_MO_SIGNALLING, BarringInfo::SERVICE_TYPE_MO_DATA,
+            BarringInfo::SERVICE_TYPE_CS_FALLBACK,   BarringInfo::SERVICE_TYPE_MMTEL_VOICE,
+            BarringInfo::SERVICE_TYPE_MMTEL_VIDEO,   BarringInfo::SERVICE_TYPE_EMERGENCY,
+            BarringInfo::SERVICE_TYPE_SMS,
+    };
+
+    static const std::set<int> NGRA_SERVICES = {
+            BarringInfo::SERVICE_TYPE_MO_SIGNALLING, BarringInfo::SERVICE_TYPE_MO_DATA,
+            BarringInfo::SERVICE_TYPE_CS_FALLBACK,   BarringInfo::SERVICE_TYPE_MMTEL_VOICE,
+            BarringInfo::SERVICE_TYPE_MMTEL_VIDEO,   BarringInfo::SERVICE_TYPE_EMERGENCY,
+            BarringInfo::SERVICE_TYPE_SMS,           BarringInfo::SERVICE_TYPE_OPERATOR_1,
+            BarringInfo::SERVICE_TYPE_OPERATOR_2,    BarringInfo::SERVICE_TYPE_OPERATOR_3,
+            BarringInfo::SERVICE_TYPE_OPERATOR_4,    BarringInfo::SERVICE_TYPE_OPERATOR_5,
+            BarringInfo::SERVICE_TYPE_OPERATOR_6,    BarringInfo::SERVICE_TYPE_OPERATOR_7,
+            BarringInfo::SERVICE_TYPE_OPERATOR_8,    BarringInfo::SERVICE_TYPE_OPERATOR_9,
+            BarringInfo::SERVICE_TYPE_OPERATOR_10,   BarringInfo::SERVICE_TYPE_OPERATOR_11,
+            BarringInfo::SERVICE_TYPE_OPERATOR_12,   BarringInfo::SERVICE_TYPE_OPERATOR_13,
+            BarringInfo::SERVICE_TYPE_OPERATOR_14,   BarringInfo::SERVICE_TYPE_OPERATOR_15,
+            BarringInfo::SERVICE_TYPE_OPERATOR_16,   BarringInfo::SERVICE_TYPE_OPERATOR_17,
+            BarringInfo::SERVICE_TYPE_OPERATOR_18,   BarringInfo::SERVICE_TYPE_OPERATOR_19,
+            BarringInfo::SERVICE_TYPE_OPERATOR_20,   BarringInfo::SERVICE_TYPE_OPERATOR_21,
+            BarringInfo::SERVICE_TYPE_OPERATOR_22,   BarringInfo::SERVICE_TYPE_OPERATOR_23,
+            BarringInfo::SERVICE_TYPE_OPERATOR_24,   BarringInfo::SERVICE_TYPE_OPERATOR_25,
+            BarringInfo::SERVICE_TYPE_OPERATOR_26,   BarringInfo::SERVICE_TYPE_OPERATOR_27,
+            BarringInfo::SERVICE_TYPE_OPERATOR_28,   BarringInfo::SERVICE_TYPE_OPERATOR_29,
+            BarringInfo::SERVICE_TYPE_OPERATOR_30,   BarringInfo::SERVICE_TYPE_OPERATOR_31,
+    };
+
+    const std::set<int>* compareTo = nullptr;
+
+    switch (radioRsp_network->barringCellIdentity.getTag()) {
+        case CellIdentity::Tag::wcdma:
+            // fall through
+        case CellIdentity::Tag::tdscdma:
+            compareTo = &UTRA_SERVICES;
+            break;
+        case CellIdentity::Tag::lte:
+            compareTo = &EUTRA_SERVICES;
+            break;
+        case CellIdentity::Tag::nr:
+            compareTo = &NGRA_SERVICES;
+            break;
+        case CellIdentity::Tag::cdma:
+            // fall through
+        default:
+            FAIL();
+            break;
+    }
+
+    std::set<int> diff;
+
+    std::set_difference(reportedServices.begin(), reportedServices.end(), compareTo->begin(),
+                        compareTo->end(), std::inserter(diff, diff.begin()));
+}
+
+/*
+ * Test IRadioNetwork.getSignalStrength() for the response returned.
+ */
+TEST_P(RadioNetworkTest, getSignalStrength) {
+    serial = GetRandomSerialNumber();
+
+    radio_network->getSignalStrength(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        EXPECT_EQ(RadioError::NONE, radioRsp_network->rspInfo.error);
+    } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+                                     {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE}));
+    }
+}
+
+/*
+ * Test IRadioNetwork.getCellInfoList() for the response returned.
+ */
+TEST_P(RadioNetworkTest, getCellInfoList) {
+    serial = GetRandomSerialNumber();
+
+    ndk::ScopedAStatus res = radio_network->getCellInfoList(serial);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    ALOGI("getCellInfoList, rspInfo.error = %s\n",
+          toString(radioRsp_network->rspInfo.error).c_str());
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+                                 {RadioError::NONE, RadioError::NO_NETWORK_FOUND}));
+}
+
+/*
+ * Test IRadioNetwork.getVoiceRegistrationState() for the response returned.
+ */
+TEST_P(RadioNetworkTest, getVoiceRegistrationState) {
+    serial = GetRandomSerialNumber();
+
+    ndk::ScopedAStatus res = radio_network->getVoiceRegistrationState(serial);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    ALOGI("getVoiceRegistrationStateResponse, rspInfo.error = %s\n",
+          toString(radioRsp_network->rspInfo.error).c_str());
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+                                 {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE}));
+}
+
+/*
+ * Test IRadioNetwork.getDataRegistrationState() for the response returned.
+ */
+TEST_P(RadioNetworkTest, getDataRegistrationState) {
+    serial = GetRandomSerialNumber();
+
+    ndk::ScopedAStatus res = radio_network->getDataRegistrationState(serial);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    ALOGI("getDataRegistrationStateResponse, rspInfo.error = %s\n",
+          toString(radioRsp_network->rspInfo.error).c_str());
+    ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp_network->rspInfo.error,
+            {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::NOT_PROVISIONED}));
+
+    // Check the mcc [0, 999] and mnc [0, 999].
+    std::string mcc;
+    std::string mnc;
+    bool checkMccMnc = true;
+    CellIdentity cellIdentity = radioRsp_network->dataRegResp.cellIdentity;
+    switch (cellIdentity.getTag()) {
+        case CellIdentity::noinit: {
+            checkMccMnc = false;
+            break;
+        }
+        case CellIdentity::gsm: {
+            CellIdentityGsm cig = cellIdentity.get<CellIdentity::gsm>();
+            mcc = cig.mcc;
+            mnc = cig.mnc;
+            break;
+        }
+        case CellIdentity::wcdma: {
+            CellIdentityWcdma ciw = cellIdentity.get<CellIdentity::wcdma>();
+            mcc = ciw.mcc;
+            mnc = ciw.mnc;
+            break;
+        }
+        case CellIdentity::tdscdma: {
+            CellIdentityTdscdma cit = cellIdentity.get<CellIdentity::tdscdma>();
+            mcc = cit.mcc;
+            mnc = cit.mnc;
+            break;
+        }
+        case CellIdentity::cdma: {
+            // CellIdentityCdma has no mcc/mnc
+            CellIdentityCdma cic = cellIdentity.get<CellIdentity::cdma>();
+            checkMccMnc = false;
+            break;
+        }
+        case CellIdentity::lte: {
+            CellIdentityLte cil = cellIdentity.get<CellIdentity::lte>();
+            mcc = cil.mcc;
+            mnc = cil.mnc;
+            break;
+        }
+        case CellIdentity::nr: {
+            CellIdentityNr cin = cellIdentity.get<CellIdentity::nr>();
+            mcc = cin.mcc;
+            mnc = cin.mnc;
+            break;
+        }
+    }
+
+    // 32 bit system might return invalid mcc and mnc string "\xff\xff..."
+    if (checkMccMnc && mcc.size() < 4 && mnc.size() < 4) {
+        int mcc_int = stoi(mcc);
+        int mnc_int = stoi(mnc);
+        EXPECT_TRUE(mcc_int >= 0 && mcc_int <= 999);
+        EXPECT_TRUE(mnc_int >= 0 && mnc_int <= 999);
+    }
+
+    // Check for access technology specific info
+    AccessTechnologySpecificInfo info = radioRsp_network->dataRegResp.accessTechnologySpecificInfo;
+    RadioTechnology rat = radioRsp_network->dataRegResp.rat;
+    // TODO: add logic for cdmaInfo
+    if (rat == RadioTechnology::LTE || rat == RadioTechnology::LTE_CA) {
+        ASSERT_EQ(info.getTag(), AccessTechnologySpecificInfo::eutranInfo);
+    } else if (rat == RadioTechnology::NR) {
+        ASSERT_EQ(info.getTag(), AccessTechnologySpecificInfo::ngranNrVopsInfo);
+    }
+}
+
+/*
+ * Test IRadioNetwork.getAvailableBandModes() for the response returned.
+ */
+TEST_P(RadioNetworkTest, getAvailableBandModes) {
+    serial = GetRandomSerialNumber();
+
+    ndk::ScopedAStatus res = radio_network->getAvailableBandModes(serial);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+    ALOGI("getAvailableBandModes, rspInfo.error = %s\n",
+          toString(radioRsp_network->rspInfo.error).c_str());
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+                                 {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
+                                  RadioError::MODEM_ERR, RadioError::INTERNAL_ERR,
+                                  // If REQUEST_NOT_SUPPORTED is returned, then it should also be
+                                  // returned for setBandMode().
+                                  RadioError::REQUEST_NOT_SUPPORTED}));
+    bool hasUnspecifiedBandMode = false;
+    if (radioRsp_network->rspInfo.error == RadioError::NONE) {
+        for (const RadioBandMode& mode : radioRsp_network->radioBandModes) {
+            // Automatic mode selection must be supported
+            if (mode == RadioBandMode::BAND_MODE_UNSPECIFIED) hasUnspecifiedBandMode = true;
+        }
+        ASSERT_TRUE(hasUnspecifiedBandMode);
+    }
+}
+
+/*
+ * Test IRadioNetwork.setIndicationFilter()
+ */
+TEST_P(RadioNetworkTest, setIndicationFilter) {
+    serial = GetRandomSerialNumber();
+
+    ndk::ScopedAStatus res =
+            radio_network->setIndicationFilter(serial, static_cast<int>(IndicationFilter::ALL));
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    ALOGI("setIndicationFilter, rspInfo.error = %s\n",
+          toString(radioRsp_network->rspInfo.error).c_str());
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error, {RadioError::NONE}));
+}
+
+/*
+ * Test IRadioNetwork.setBarringPassword() for the response returned.
+ */
+TEST_P(RadioNetworkTest, setBarringPassword) {
+    serial = GetRandomSerialNumber();
+    std::string facility = "";
+    std::string oldPassword = "";
+    std::string newPassword = "";
+
+    radio_network->setBarringPassword(serial, facility, oldPassword, newPassword);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+                                     {RadioError::NONE, RadioError::FDN_CHECK_FAILURE,
+                                      RadioError::INVALID_ARGUMENTS, RadioError::MODEM_ERR},
+                                     CHECK_GENERAL_ERROR));
+    }
+}
+
+/*
+ * Test IRadioNetwork.setSuppServiceNotifications() for the response returned.
+ */
+TEST_P(RadioNetworkTest, setSuppServiceNotifications) {
+    serial = GetRandomSerialNumber();
+    bool enable = false;
+
+    radio_network->setSuppServiceNotifications(serial, enable);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+                                     {RadioError::NONE, RadioError::SIM_ABSENT}));
+    }
+}
+
+/*
+ * Test IRadioNetwork.getImsRegistrationState() for the response returned.
+ */
+TEST_P(RadioNetworkTest, getImsRegistrationState) {
+    serial = GetRandomSerialNumber();
+
+    radio_network->getImsRegistrationState(serial);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_network->rspInfo.error,
+                {RadioError::NONE, RadioError::MODEM_ERR, RadioError::INVALID_MODEM_STATE},
+                CHECK_GENERAL_ERROR));
+    }
+}
+
+/*
+ * Test IRadioNetwork.getOperator() for the response returned.
+ */
+TEST_P(RadioNetworkTest, getOperator) {
+    LOG(DEBUG) << "getOperator";
+    serial = GetRandomSerialNumber();
+
+    radio_network->getOperator(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        EXPECT_EQ(RadioError::NONE, radioRsp_network->rspInfo.error);
+    }
+    LOG(DEBUG) << "getOperator finished";
+}
+
+/*
+ * Test IRadioNetwork.getNetworkSelectionMode() for the response returned.
+ */
+TEST_P(RadioNetworkTest, getNetworkSelectionMode) {
+    LOG(DEBUG) << "getNetworkSelectionMode";
+    serial = GetRandomSerialNumber();
+
+    radio_network->getNetworkSelectionMode(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        EXPECT_EQ(RadioError::NONE, radioRsp_network->rspInfo.error);
+    }
+    LOG(DEBUG) << "getNetworkSelectionMode finished";
+}
+
+/*
+ * Test IRadioNetwork.setNetworkSelectionModeAutomatic() for the response returned.
+ */
+TEST_P(RadioNetworkTest, setNetworkSelectionModeAutomatic) {
+    LOG(DEBUG) << "setNetworkSelectionModeAutomatic";
+    serial = GetRandomSerialNumber();
+
+    radio_network->setNetworkSelectionModeAutomatic(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+                                     {RadioError::NONE, RadioError::ILLEGAL_SIM_OR_ME,
+                                      RadioError::OPERATION_NOT_ALLOWED},
+                                     CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "setNetworkSelectionModeAutomatic finished";
+}
+
+/*
+ * Test IRadioNetwork.getAvailableNetworks() for the response returned.
+ */
+TEST_P(RadioNetworkTest, getAvailableNetworks) {
+    LOG(DEBUG) << "getAvailableNetworks";
+    serial = GetRandomSerialNumber();
+
+    radio_network->getAvailableNetworks(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+    ASSERT_TRUE(radioRsp_network->rspInfo.type == RadioResponseType::SOLICITED ||
+                radioRsp_network->rspInfo.type == RadioResponseType::SOLICITED_ACK_EXP);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_network->rspInfo.error,
+                {RadioError::NONE, RadioError::CANCELLED, RadioError::DEVICE_IN_USE,
+                 RadioError::MODEM_ERR, RadioError::OPERATION_NOT_ALLOWED},
+                CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "getAvailableNetworks finished";
+}
+
+/*
+ * Test IRadioNetwork.setBandMode() for the response returned.
+ */
+TEST_P(RadioNetworkTest, setBandMode) {
+    LOG(DEBUG) << "setBandMode";
+    serial = GetRandomSerialNumber();
+
+    radio_network->setBandMode(serial, RadioBandMode::BAND_MODE_USA);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error, {RadioError::NONE},
+                                     CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "setBandMode finished";
+}
+
+/*
+ * Test IRadioNetwork.setLocationUpdates() for the response returned.
+ */
+TEST_P(RadioNetworkTest, setLocationUpdates) {
+    LOG(DEBUG) << "setLocationUpdates";
+    serial = GetRandomSerialNumber();
+
+    radio_network->setLocationUpdates(serial, true);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+                                     {RadioError::NONE, RadioError::SIM_ABSENT}));
+    }
+    LOG(DEBUG) << "setLocationUpdates finished";
+}
+
+/*
+ * Test IRadioNetwork.setCdmaRoamingPreference() for the response returned.
+ */
+TEST_P(RadioNetworkTest, setCdmaRoamingPreference) {
+    LOG(DEBUG) << "setCdmaRoamingPreference";
+    serial = GetRandomSerialNumber();
+
+    radio_network->setCdmaRoamingPreference(serial, CdmaRoamingType::HOME_NETWORK);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_network->rspInfo.error,
+                {RadioError::NONE, RadioError::SIM_ABSENT, RadioError::REQUEST_NOT_SUPPORTED}));
+    }
+    LOG(DEBUG) << "setCdmaRoamingPreference finished";
+}
+
+/*
+ * Test IRadioNetwork.getCdmaRoamingPreference() for the response returned.
+ */
+TEST_P(RadioNetworkTest, getCdmaRoamingPreference) {
+    LOG(DEBUG) << "getCdmaRoamingPreference";
+    serial = GetRandomSerialNumber();
+
+    radio_network->getCdmaRoamingPreference(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(
+                CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+                                 {RadioError::NONE, RadioError::SIM_ABSENT, RadioError::MODEM_ERR},
+                                 CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "getCdmaRoamingPreference finished";
+}
+
+/*
+ * Test IRadioNetwork.getVoiceRadioTechnology() for the response returned.
+ */
+TEST_P(RadioNetworkTest, getVoiceRadioTechnology) {
+    LOG(DEBUG) << "getVoiceRadioTechnology";
+    serial = GetRandomSerialNumber();
+
+    radio_network->getVoiceRadioTechnology(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        EXPECT_EQ(RadioError::NONE, radioRsp_network->rspInfo.error);
+    }
+    LOG(DEBUG) << "getVoiceRadioTechnology finished";
+}
+
+/*
+ * Test IRadioNetwork.setCellInfoListRate() for the response returned.
+ */
+TEST_P(RadioNetworkTest, setCellInfoListRate) {
+    LOG(DEBUG) << "setCellInfoListRate";
+    serial = GetRandomSerialNumber();
+
+    radio_network->setCellInfoListRate(serial, 10);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
+                                     {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+    }
+    LOG(DEBUG) << "setCellInfoListRate finished";
+}
+
+/*
+ * Test IRadioNetwork.supplyNetworkDepersonalization() for the response returned.
+ */
+TEST_P(RadioNetworkTest, supplyNetworkDepersonalization) {
+    LOG(DEBUG) << "supplyNetworkDepersonalization";
+    serial = GetRandomSerialNumber();
+
+    radio_network->supplyNetworkDepersonalization(serial, std::string("test"));
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_network->rspInfo.error,
+                {RadioError::NONE, RadioError::INVALID_ARGUMENTS, RadioError::INTERNAL_ERR,
+                 RadioError::INVALID_SIM_STATE, RadioError::MODEM_ERR, RadioError::NO_MEMORY,
+                 RadioError::PASSWORD_INCORRECT, RadioError::SIM_ABSENT, RadioError::SYSTEM_ERR}));
+    }
+    LOG(DEBUG) << "supplyNetworkDepersonalization finished";
+}
diff --git a/radio/aidl/vts/radio_network_utils.h b/radio/aidl/vts/radio_network_utils.h
new file mode 100644
index 0000000..29ba2f2
--- /dev/null
+++ b/radio/aidl/vts/radio_network_utils.h
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/radio/network/BnRadioNetworkIndication.h>
+#include <aidl/android/hardware/radio/network/BnRadioNetworkResponse.h>
+#include <aidl/android/hardware/radio/network/IRadioNetwork.h>
+
+#include "radio_aidl_hal_utils.h"
+
+using namespace aidl::android::hardware::radio::network;
+
+class RadioNetworkTest;
+
+/* Callback class for radio network response */
+class RadioNetworkResponse : public BnRadioNetworkResponse {
+  protected:
+    RadioServiceTest& parent_network;
+
+  public:
+    RadioNetworkResponse(RadioServiceTest& parent_network);
+    virtual ~RadioNetworkResponse() = default;
+
+    RadioResponseInfo rspInfo;
+    std::vector<RadioBandMode> radioBandModes;
+    std::vector<OperatorInfo> networkInfos;
+    bool isNrDualConnectivityEnabled;
+    int networkTypeBitmapResponse;
+    RegStateResult voiceRegResp;
+    RegStateResult dataRegResp;
+    CellIdentity barringCellIdentity;
+    std::vector<BarringInfo> barringInfoList;
+    UsageSetting usageSetting;
+
+    virtual ndk::ScopedAStatus acknowledgeRequest(int32_t serial) override;
+
+    virtual ndk::ScopedAStatus getAllowedNetworkTypesBitmapResponse(
+            const RadioResponseInfo& info, const int32_t networkTypeBitmap) override;
+
+    virtual ndk::ScopedAStatus getAvailableBandModesResponse(
+            const RadioResponseInfo& info, const std::vector<RadioBandMode>& bandModes) override;
+
+    virtual ndk::ScopedAStatus getAvailableNetworksResponse(
+            const RadioResponseInfo& info, const std::vector<OperatorInfo>& networkInfos) override;
+
+    virtual ndk::ScopedAStatus getBarringInfoResponse(
+            const RadioResponseInfo& info, const CellIdentity& cellIdentity,
+            const std::vector<BarringInfo>& barringInfos) override;
+
+    virtual ndk::ScopedAStatus getCdmaRoamingPreferenceResponse(const RadioResponseInfo& info,
+                                                                CdmaRoamingType type) override;
+
+    virtual ndk::ScopedAStatus getCellInfoListResponse(
+            const RadioResponseInfo& info, const std::vector<CellInfo>& cellInfo) override;
+
+    virtual ndk::ScopedAStatus getDataRegistrationStateResponse(
+            const RadioResponseInfo& info, const RegStateResult& dataRegResponse) override;
+
+    virtual ndk::ScopedAStatus getImsRegistrationStateResponse(
+            const RadioResponseInfo& info, bool isRegistered,
+            RadioTechnologyFamily ratFamily) override;
+
+    virtual ndk::ScopedAStatus getNetworkSelectionModeResponse(const RadioResponseInfo& info,
+                                                               bool manual) override;
+
+    virtual ndk::ScopedAStatus getOperatorResponse(const RadioResponseInfo& info,
+                                                   const std::string& longName,
+                                                   const std::string& shortName,
+                                                   const std::string& numeric) override;
+
+    virtual ndk::ScopedAStatus getSignalStrengthResponse(
+            const RadioResponseInfo& info, const SignalStrength& sigStrength) override;
+
+    virtual ndk::ScopedAStatus getSystemSelectionChannelsResponse(
+            const RadioResponseInfo& info,
+            const std::vector<RadioAccessSpecifier>& specifier) override;
+
+    virtual ndk::ScopedAStatus getUsageSettingResponse(const RadioResponseInfo& info,
+                                                       UsageSetting usageSetting) override;
+
+    virtual ndk::ScopedAStatus getVoiceRadioTechnologyResponse(const RadioResponseInfo& info,
+                                                               RadioTechnology rat) override;
+
+    virtual ndk::ScopedAStatus getVoiceRegistrationStateResponse(
+            const RadioResponseInfo& info, const RegStateResult& voiceRegResponse) override;
+
+    virtual ndk::ScopedAStatus isNrDualConnectivityEnabledResponse(const RadioResponseInfo& info,
+                                                                   bool isEnabled) override;
+
+    virtual ndk::ScopedAStatus setAllowedNetworkTypesBitmapResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setBandModeResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setBarringPasswordResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setCdmaRoamingPreferenceResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setCellInfoListRateResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setIndicationFilterResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setLinkCapacityReportingCriteriaResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setLocationUpdatesResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setNetworkSelectionModeAutomaticResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setNetworkSelectionModeManualResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setNrDualConnectivityStateResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setSignalStrengthReportingCriteriaResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setSuppServiceNotificationsResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setSystemSelectionChannelsResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setUsageSettingResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus startNetworkScanResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus stopNetworkScanResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus supplyNetworkDepersonalizationResponse(
+            const RadioResponseInfo& info, int32_t remainingRetries) override;
+};
+
+/* Callback class for radio network indication */
+class RadioNetworkIndication : public BnRadioNetworkIndication {
+  protected:
+    RadioServiceTest& parent_network;
+
+  public:
+    RadioNetworkIndication(RadioServiceTest& parent_network);
+    virtual ~RadioNetworkIndication() = default;
+
+    virtual ndk::ScopedAStatus barringInfoChanged(
+            RadioIndicationType type, const CellIdentity& cellIdentity,
+            const std::vector<BarringInfo>& barringInfos) override;
+
+    virtual ndk::ScopedAStatus cdmaPrlChanged(RadioIndicationType type, int32_t version) override;
+
+    virtual ndk::ScopedAStatus cellInfoList(RadioIndicationType type,
+                                            const std::vector<CellInfo>& records) override;
+
+    virtual ndk::ScopedAStatus currentLinkCapacityEstimate(
+            RadioIndicationType type, const LinkCapacityEstimate& lce) override;
+
+    virtual ndk::ScopedAStatus currentPhysicalChannelConfigs(
+            RadioIndicationType type, const std::vector<PhysicalChannelConfig>& configs) override;
+
+    virtual ndk::ScopedAStatus currentSignalStrength(RadioIndicationType type,
+                                                     const SignalStrength& signalStrength) override;
+
+    virtual ndk::ScopedAStatus imsNetworkStateChanged(RadioIndicationType type) override;
+
+    virtual ndk::ScopedAStatus networkScanResult(RadioIndicationType type,
+                                                 const NetworkScanResult& result) override;
+
+    virtual ndk::ScopedAStatus networkStateChanged(RadioIndicationType type) override;
+
+    virtual ndk::ScopedAStatus nitzTimeReceived(RadioIndicationType type,
+                                                const std::string& nitzTime, int64_t receivedTimeMs,
+                                                int64_t ageMs) override;
+
+    virtual ndk::ScopedAStatus registrationFailed(RadioIndicationType type,
+                                                  const CellIdentity& cellIdentity,
+                                                  const std::string& chosenPlmn, int32_t domain,
+                                                  int32_t causeCode,
+                                                  int32_t additionalCauseCode) override;
+
+    virtual ndk::ScopedAStatus restrictedStateChanged(RadioIndicationType type,
+                                                      PhoneRestrictedState state) override;
+
+    virtual ndk::ScopedAStatus suppSvcNotify(RadioIndicationType type,
+                                             const SuppSvcNotification& suppSvc) override;
+
+    virtual ndk::ScopedAStatus voiceRadioTechChanged(RadioIndicationType type,
+                                                     RadioTechnology rat) override;
+};
+
+// The main test class for Radio AIDL Network.
+class RadioNetworkTest : public ::testing::TestWithParam<std::string>, public RadioServiceTest {
+  public:
+    virtual void SetUp() override;
+
+    /* radio network service handle */
+    std::shared_ptr<IRadioNetwork> radio_network;
+    /* radio network response handle */
+    std::shared_ptr<RadioNetworkResponse> radioRsp_network;
+    /* radio network indication handle */
+    std::shared_ptr<RadioNetworkIndication> radioInd_network;
+
+    void invokeAndExpectResponse(std::function<ndk::ScopedAStatus(int32_t serial)> request,
+                                 std::vector<RadioError> errors_to_check);
+
+    // Helper function to reduce copy+paste
+    void testSetUsageSetting_InvalidValues(std::vector<RadioError> errors);
+
+    void stopNetworkScan();
+};
diff --git a/radio/aidl/vts/radio_sim_indication.cpp b/radio/aidl/vts/radio_sim_indication.cpp
new file mode 100644
index 0000000..c03d947
--- /dev/null
+++ b/radio/aidl/vts/radio_sim_indication.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "radio_sim_utils.h"
+
+RadioSimIndication::RadioSimIndication(RadioServiceTest& parent) : parent_sim(parent) {}
+
+ndk::ScopedAStatus RadioSimIndication::carrierInfoForImsiEncryption(RadioIndicationType /*info*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimIndication::cdmaSubscriptionSourceChanged(
+        RadioIndicationType /*type*/, CdmaSubscriptionSource /*cdmaSource*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimIndication::simPhonebookChanged(RadioIndicationType /*type*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimIndication::simPhonebookRecordsReceived(
+        RadioIndicationType /*type*/, PbReceivedStatus /*status*/,
+        const std::vector<PhonebookRecordInfo>& /*records*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimIndication::simRefresh(RadioIndicationType /*type*/,
+                                                  const SimRefreshResult& /*refreshResult*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimIndication::simStatusChanged(RadioIndicationType /*type*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimIndication::stkEventNotify(RadioIndicationType /*type*/,
+                                                      const std::string& /*cmd*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimIndication::stkProactiveCommand(RadioIndicationType /*type*/,
+                                                           const std::string& /*cmd*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimIndication::stkSessionEnd(RadioIndicationType /*type*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimIndication::subscriptionStatusChanged(RadioIndicationType /*type*/,
+                                                                 bool /*activate*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimIndication::uiccApplicationsEnablementChanged(
+        RadioIndicationType /*type*/, bool /*enabled*/) {
+    return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_sim_response.cpp b/radio/aidl/vts/radio_sim_response.cpp
new file mode 100644
index 0000000..391c9cb
--- /dev/null
+++ b/radio/aidl/vts/radio_sim_response.cpp
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "radio_sim_utils.h"
+
+RadioSimResponse::RadioSimResponse(RadioServiceTest& parent) : parent_sim(parent) {}
+
+ndk::ScopedAStatus RadioSimResponse::acknowledgeRequest(int32_t /*serial*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::areUiccApplicationsEnabledResponse(
+        const RadioResponseInfo& info, bool enabled) {
+    rspInfo = info;
+    areUiccApplicationsEnabled = enabled;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::changeIccPin2ForAppResponse(const RadioResponseInfo& info,
+                                                                 int32_t /*remainingRetries*/) {
+    rspInfo = info;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::changeIccPinForAppResponse(const RadioResponseInfo& info,
+                                                                int32_t /*remainingRetries*/) {
+    rspInfo = info;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::enableUiccApplicationsResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::getAllowedCarriersResponse(
+        const RadioResponseInfo& info, const CarrierRestrictions& carriers,
+        SimLockMultiSimPolicy multiSimPolicy) {
+    rspInfo = info;
+    carrierRestrictionsResp = carriers;
+    multiSimPolicyResp = multiSimPolicy;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::getCdmaSubscriptionResponse(
+        const RadioResponseInfo& info, const std::string& /*mdn*/, const std::string& /*hSid*/,
+        const std::string& /*hNid*/, const std::string& /*min*/, const std::string& /*prl*/) {
+    rspInfo = info;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::getCdmaSubscriptionSourceResponse(
+        const RadioResponseInfo& info, CdmaSubscriptionSource /*source*/) {
+    rspInfo = info;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::getFacilityLockForAppResponse(const RadioResponseInfo& info,
+                                                                   int32_t /*response*/) {
+    rspInfo = info;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::getIccCardStatusResponse(const RadioResponseInfo& info,
+                                                              const CardStatus& card_status) {
+    rspInfo = info;
+    cardStatus = card_status;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::getImsiForAppResponse(const RadioResponseInfo& info,
+                                                           const std::string& imsi_str) {
+    rspInfo = info;
+    imsi = imsi_str;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::getSimPhonebookCapacityResponse(
+        const RadioResponseInfo& info, const PhonebookCapacity& pbCapacity) {
+    rspInfo = info;
+    capacity = pbCapacity;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::getSimPhonebookRecordsResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::iccCloseLogicalChannelResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::iccIoForAppResponse(const RadioResponseInfo& info,
+                                                         const IccIoResult& /*iccIo*/) {
+    rspInfo = info;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::iccOpenLogicalChannelResponse(
+        const RadioResponseInfo& info, int32_t /*channelId*/,
+        const std::vector<uint8_t>& /*selectResponse*/) {
+    rspInfo = info;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::iccTransmitApduBasicChannelResponse(
+        const RadioResponseInfo& info, const IccIoResult& /*result*/) {
+    rspInfo = info;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::iccTransmitApduLogicalChannelResponse(
+        const RadioResponseInfo& info, const IccIoResult& /*result*/) {
+    rspInfo = info;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::reportStkServiceIsRunningResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::requestIccSimAuthenticationResponse(
+        const RadioResponseInfo& info, const IccIoResult& /*result*/) {
+    rspInfo = info;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::sendEnvelopeResponse(const RadioResponseInfo& info,
+                                                          const std::string& /*commandResponse*/) {
+    rspInfo = info;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::sendEnvelopeWithStatusResponse(const RadioResponseInfo& info,
+                                                                    const IccIoResult& /*iccIo*/) {
+    rspInfo = info;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::sendTerminalResponseToSimResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::setAllowedCarriersResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::setCarrierInfoForImsiEncryptionResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::setCdmaSubscriptionSourceResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::setFacilityLockForAppResponse(const RadioResponseInfo& info,
+                                                                   int32_t /*retry*/) {
+    rspInfo = info;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::setSimCardPowerResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::setUiccSubscriptionResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::supplyIccPin2ForAppResponse(const RadioResponseInfo& info,
+                                                                 int32_t /*remainingRetries*/) {
+    rspInfo = info;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::supplyIccPinForAppResponse(const RadioResponseInfo& info,
+                                                                int32_t /*remainingRetries*/) {
+    rspInfo = info;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::supplyIccPuk2ForAppResponse(const RadioResponseInfo& info,
+                                                                 int32_t /*remainingRetries*/) {
+    rspInfo = info;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::supplyIccPukForAppResponse(const RadioResponseInfo& info,
+                                                                int32_t /*remainingRetries*/) {
+    rspInfo = info;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::supplySimDepersonalizationResponse(
+        const RadioResponseInfo& info, PersoSubstate /*persoType*/, int32_t /*remainingRetries*/) {
+    rspInfo = info;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioSimResponse::updateSimPhonebookRecordsResponse(
+        const RadioResponseInfo& info, int32_t recordIndex) {
+    rspInfo = info;
+    updatedRecordIndex = recordIndex;
+    parent_sim.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_sim_test.cpp b/radio/aidl/vts/radio_sim_test.cpp
new file mode 100644
index 0000000..e69247d
--- /dev/null
+++ b/radio/aidl/vts/radio_sim_test.cpp
@@ -0,0 +1,1029 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aidl/android/hardware/radio/RadioConst.h>
+#include <aidl/android/hardware/radio/config/IRadioConfig.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+
+#include "radio_sim_utils.h"
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
+
+void RadioSimTest::SetUp() {
+    std::string serviceName = GetParam();
+
+    if (!isServiceValidForDeviceConfiguration(serviceName)) {
+        ALOGI("Skipped the test due to device configuration.");
+        GTEST_SKIP();
+    }
+
+    radio_sim = IRadioSim::fromBinder(
+            ndk::SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+    ASSERT_NE(nullptr, radio_sim.get());
+
+    radioRsp_sim = ndk::SharedRefBase::make<RadioSimResponse>(*this);
+    ASSERT_NE(nullptr, radioRsp_sim.get());
+
+    count_ = 0;
+
+    radioInd_sim = ndk::SharedRefBase::make<RadioSimIndication>(*this);
+    ASSERT_NE(nullptr, radioInd_sim.get());
+
+    radio_sim->setResponseFunctions(radioRsp_sim, radioInd_sim);
+    // Assert SIM is present before testing
+    updateSimCardStatus();
+    EXPECT_EQ(CardStatus::STATE_PRESENT, cardStatus.cardState);
+
+    // Assert IRadioConfig exists before testing
+    radio_config = config::IRadioConfig::fromBinder(ndk::SpAIBinder(
+            AServiceManager_waitForService("android.hardware.radio.config.IRadioConfig/default")));
+    ASSERT_NE(nullptr, radio_config.get());
+}
+
+void RadioSimTest::updateSimCardStatus() {
+    serial = GetRandomSerialNumber();
+    radio_sim->getIccCardStatus(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+    EXPECT_EQ(RadioError::NONE, radioRsp_sim->rspInfo.error);
+}
+
+/*
+ * Test IRadioSim.setSimCardPower() for the response returned.
+ */
+TEST_P(RadioSimTest, setSimCardPower) {
+    /* Test setSimCardPower power down */
+    serial = GetRandomSerialNumber();
+    radio_sim->setSimCardPower(serial, CardPowerState::POWER_DOWN);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+                                 {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
+                                  RadioError::RADIO_NOT_AVAILABLE, RadioError::SIM_ERR}));
+
+    // setSimCardPower does not return  until the request is handled, and should not trigger
+    // CardStatus::STATE_ABSENT when turning off power
+    if (radioRsp_sim->rspInfo.error == RadioError::NONE) {
+        /* Wait some time for setting sim power down and then verify it */
+        updateSimCardStatus();
+        // We cannot assert the consistency of CardState here due to b/203031664
+        // EXPECT_EQ(CardStatus::STATE_PRESENT, cardStatus.cardState);
+        // applications should be an empty vector of AppStatus
+        EXPECT_EQ(0, cardStatus.applications.size());
+    }
+
+    // Give some time for modem to fully power down the SIM card
+    sleep(MODEM_SET_SIM_POWER_DELAY_IN_SECONDS);
+
+    /* Test setSimCardPower power up */
+    serial = GetRandomSerialNumber();
+    radio_sim->setSimCardPower(serial, CardPowerState::POWER_UP);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+                                 {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
+                                  RadioError::RADIO_NOT_AVAILABLE, RadioError::SIM_ERR}));
+
+    // Give some time for modem to fully power up the SIM card
+    sleep(MODEM_SET_SIM_POWER_DELAY_IN_SECONDS);
+
+    // setSimCardPower does not return  until the request is handled. Just verify that we still
+    // have CardStatus::STATE_PRESENT after turning the power back on
+    if (radioRsp_sim->rspInfo.error == RadioError::NONE) {
+        updateSimCardStatus();
+        updateSimSlotStatus(cardStatus.slotMap.physicalSlotId);
+        EXPECT_EQ(CardStatus::STATE_PRESENT, cardStatus.cardState);
+        EXPECT_EQ(CardStatus::STATE_PRESENT, slotStatus.cardState);
+        if (CardStatus::STATE_PRESENT == slotStatus.cardState) {
+            ASSERT_TRUE(slotStatus.portInfo[0].portActive);
+            EXPECT_EQ(0, cardStatus.slotMap.portId);
+        }
+    }
+}
+
+/*
+ * Test IRadioSim.setCarrierInfoForImsiEncryption() for the response returned.
+ */
+TEST_P(RadioSimTest, setCarrierInfoForImsiEncryption) {
+    serial = GetRandomSerialNumber();
+    ImsiEncryptionInfo imsiInfo;
+    imsiInfo.mcc = "310";
+    imsiInfo.mnc = "004";
+    imsiInfo.carrierKey = (std::vector<uint8_t>){1, 2, 3, 4, 5, 6};
+    imsiInfo.keyIdentifier = "Test";
+    imsiInfo.expirationTime = 20180101;
+    imsiInfo.keyType = ImsiEncryptionInfo::PUBLIC_KEY_TYPE_EPDG;
+
+    radio_sim->setCarrierInfoForImsiEncryption(serial, imsiInfo);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+                                     {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+    }
+}
+
+/*
+ * Test IRadioSim.getSimPhonebookRecords() for the response returned.
+ */
+TEST_P(RadioSimTest, getSimPhonebookRecords) {
+    serial = GetRandomSerialNumber();
+    radio_sim->getSimPhonebookRecords(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(
+                CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+                                 {RadioError::INVALID_SIM_STATE, RadioError::RADIO_NOT_AVAILABLE,
+                                  RadioError::MODEM_ERR, RadioError::INVALID_ARGUMENTS,
+                                  RadioError::REQUEST_NOT_SUPPORTED},
+                                 CHECK_GENERAL_ERROR));
+    } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+                                     {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED},
+                                     CHECK_GENERAL_ERROR));
+    }
+}
+
+/*
+ * Test IRadioSim.getSimPhonebookCapacity for the response returned.
+ */
+TEST_P(RadioSimTest, getSimPhonebookCapacity) {
+    serial = GetRandomSerialNumber();
+    radio_sim->getSimPhonebookCapacity(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(
+                CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+                                 {RadioError::INVALID_SIM_STATE, RadioError::RADIO_NOT_AVAILABLE,
+                                  RadioError::MODEM_ERR, RadioError::INVALID_ARGUMENTS,
+                                  RadioError::REQUEST_NOT_SUPPORTED},
+                                 CHECK_GENERAL_ERROR));
+    } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+                                     {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED},
+                                     CHECK_GENERAL_ERROR));
+
+        PhonebookCapacity pbCapacity = radioRsp_sim->capacity;
+        if (pbCapacity.maxAdnRecords > 0) {
+            EXPECT_TRUE(pbCapacity.maxNameLen > 0 && pbCapacity.maxNumberLen > 0);
+            EXPECT_TRUE(pbCapacity.usedAdnRecords <= pbCapacity.maxAdnRecords);
+        }
+
+        if (pbCapacity.maxEmailRecords > 0) {
+            EXPECT_TRUE(pbCapacity.maxEmailLen > 0);
+            EXPECT_TRUE(pbCapacity.usedEmailRecords <= pbCapacity.maxEmailRecords);
+        }
+
+        if (pbCapacity.maxAdditionalNumberRecords > 0) {
+            EXPECT_TRUE(pbCapacity.maxAdditionalNumberLen > 0);
+            EXPECT_TRUE(pbCapacity.usedAdditionalNumberRecords <=
+                        pbCapacity.maxAdditionalNumberRecords);
+        }
+    }
+}
+
+/*
+ * Test IRadioSim.updateSimPhonebookRecords() for the response returned.
+ */
+TEST_P(RadioSimTest, updateSimPhonebookRecords) {
+    serial = GetRandomSerialNumber();
+    radio_sim->getSimPhonebookCapacity(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(
+                CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+                                 {RadioError::INVALID_SIM_STATE, RadioError::RADIO_NOT_AVAILABLE,
+                                  RadioError::MODEM_ERR, RadioError::INVALID_ARGUMENTS,
+                                  RadioError::REQUEST_NOT_SUPPORTED},
+                                 CHECK_GENERAL_ERROR));
+    } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+                                     {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED},
+                                     CHECK_GENERAL_ERROR));
+        PhonebookCapacity pbCapacity = radioRsp_sim->capacity;
+
+        serial = GetRandomSerialNumber();
+        radio_sim->getSimPhonebookRecords(serial);
+
+        EXPECT_EQ(std::cv_status::no_timeout, wait());
+        EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+        EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+                                     {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED},
+                                     CHECK_GENERAL_ERROR));
+
+        if (pbCapacity.maxAdnRecords > 0 && pbCapacity.usedAdnRecords < pbCapacity.maxAdnRecords) {
+            // Add a phonebook record
+            PhonebookRecordInfo recordInfo;
+            recordInfo.recordId = 0;
+            recordInfo.name = "ABC";
+            recordInfo.number = "1234567890";
+            serial = GetRandomSerialNumber();
+            radio_sim->updateSimPhonebookRecords(serial, recordInfo);
+
+            EXPECT_EQ(std::cv_status::no_timeout, wait());
+            EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+            EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+            EXPECT_EQ(RadioError::NONE, radioRsp_sim->rspInfo.error);
+            int index = radioRsp_sim->updatedRecordIndex;
+            EXPECT_TRUE(index > 0);
+
+            // Deleted a phonebook record
+            recordInfo.recordId = index;
+            recordInfo.name = "";
+            recordInfo.number = "";
+            serial = GetRandomSerialNumber();
+            radio_sim->updateSimPhonebookRecords(serial, recordInfo);
+
+            EXPECT_EQ(std::cv_status::no_timeout, wait());
+            EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+            EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+            EXPECT_EQ(RadioError::NONE, radioRsp_sim->rspInfo.error);
+        }
+    }
+}
+
+/*
+ * Test IRadioSim.enableUiccApplications() for the response returned.
+ * For SIM ABSENT case.
+ */
+TEST_P(RadioSimTest, togglingUiccApplicationsSimAbsent) {
+    // This test case only test SIM ABSENT case.
+    if (cardStatus.cardState != CardStatus::STATE_ABSENT) return;
+
+    // Disable Uicc applications.
+    serial = GetRandomSerialNumber();
+    radio_sim->enableUiccApplications(serial, false);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+    // As SIM is absent, RadioError::SIM_ABSENT should be thrown.
+    EXPECT_EQ(RadioError::SIM_ABSENT, radioRsp_sim->rspInfo.error);
+
+    // Query Uicc application enablement.
+    serial = GetRandomSerialNumber();
+    radio_sim->areUiccApplicationsEnabled(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+    // As SIM is absent, RadioError::SIM_ABSENT should be thrown.
+    EXPECT_EQ(RadioError::SIM_ABSENT, radioRsp_sim->rspInfo.error);
+}
+
+/*
+ * Test IRadioSim.enableUiccApplications() for the response returned.
+ * For SIM PRESENT case.
+ */
+TEST_P(RadioSimTest, togglingUiccApplicationsSimPresent) {
+    // This test case only test SIM ABSENT case.
+    if (cardStatus.cardState != CardStatus::STATE_PRESENT) return;
+    if (cardStatus.applications.size() == 0) return;
+
+    // Disable Uicc applications.
+    serial = GetRandomSerialNumber();
+    radio_sim->enableUiccApplications(serial, false);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+    // As SIM is present, there shouldn't be error.
+    EXPECT_EQ(RadioError::NONE, radioRsp_sim->rspInfo.error);
+
+    // Query Uicc application enablement.
+    serial = GetRandomSerialNumber();
+    radio_sim->areUiccApplicationsEnabled(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+    // As SIM is present, there shouldn't be error.
+    EXPECT_EQ(RadioError::NONE, radioRsp_sim->rspInfo.error);
+    ASSERT_FALSE(radioRsp_sim->areUiccApplicationsEnabled);
+
+    // Enable Uicc applications.
+    serial = GetRandomSerialNumber();
+    radio_sim->enableUiccApplications(serial, true);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+    // As SIM is present, there shouldn't be error.
+    EXPECT_EQ(RadioError::NONE, radioRsp_sim->rspInfo.error);
+
+    // Query Uicc application enablement.
+    serial = GetRandomSerialNumber();
+    radio_sim->areUiccApplicationsEnabled(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+    // As SIM is present, there shouldn't be error.
+    EXPECT_EQ(RadioError::NONE, radioRsp_sim->rspInfo.error);
+    ASSERT_TRUE(radioRsp_sim->areUiccApplicationsEnabled);
+}
+
+/*
+ * Test IRadioSim.areUiccApplicationsEnabled() for the response returned.
+ */
+TEST_P(RadioSimTest, areUiccApplicationsEnabled) {
+    // Disable Uicc applications.
+    serial = GetRandomSerialNumber();
+    radio_sim->areUiccApplicationsEnabled(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+
+    // If SIM is absent, RadioError::SIM_ABSENT should be thrown. Otherwise there shouldn't be any
+    // error.
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        EXPECT_EQ(RadioError::SIM_ABSENT, radioRsp_sim->rspInfo.error);
+    } else if (cardStatus.cardState == CardStatus::STATE_PRESENT) {
+        EXPECT_EQ(RadioError::NONE, radioRsp_sim->rspInfo.error);
+    }
+}
+
+/*
+ * Test IRadioSim.getAllowedCarriers() for the response returned.
+ */
+TEST_P(RadioSimTest, getAllowedCarriers) {
+    serial = GetRandomSerialNumber();
+
+    radio_sim->getAllowedCarriers(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+                                 {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+}
+
+/**
+ * Test IRadioSim.setAllowedCarriers() for the response returned.
+ */
+TEST_P(RadioSimTest, setAllowedCarriers) {
+    serial = GetRandomSerialNumber();
+    CarrierRestrictions carrierRestrictions;
+    memset(&carrierRestrictions, 0, sizeof(carrierRestrictions));
+    carrierRestrictions.allowedCarriers.resize(1);
+    carrierRestrictions.excludedCarriers.resize(0);
+    carrierRestrictions.allowedCarriers[0].mcc = std::string("123");
+    carrierRestrictions.allowedCarriers[0].mnc = std::string("456");
+    carrierRestrictions.allowedCarriers[0].matchType = Carrier::MATCH_TYPE_ALL;
+    carrierRestrictions.allowedCarriers[0].matchData = std::string();
+    carrierRestrictions.allowedCarriersPrioritized = true;
+    SimLockMultiSimPolicy multisimPolicy = SimLockMultiSimPolicy::NO_MULTISIM_POLICY;
+
+    radio_sim->setAllowedCarriers(serial, carrierRestrictions, multisimPolicy);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+                                 {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+
+    if (radioRsp_sim->rspInfo.error == RadioError::NONE) {
+        /* Verify the update of the SIM status. This might need some time */
+        if (cardStatus.cardState != CardStatus::STATE_ABSENT) {
+            updateSimCardStatus();
+            auto startTime = std::chrono::system_clock::now();
+            while (cardStatus.cardState != CardStatus::STATE_RESTRICTED &&
+                   std::chrono::duration_cast<std::chrono::seconds>(
+                           std::chrono::system_clock::now() - startTime)
+                                   .count() < 30) {
+                /* Set 2 seconds as interval to check card status */
+                sleep(2);
+                updateSimCardStatus();
+            }
+            // TODO: uncomment once CF fully supports setAllowedCarriers
+            // EXPECT_EQ(CardStatus::STATE_RESTRICTED, cardStatus.cardState);
+        }
+
+        /* Verify that configuration was set correctly, retrieving it from the modem */
+        serial = GetRandomSerialNumber();
+
+        radio_sim->getAllowedCarriers(serial);
+        EXPECT_EQ(std::cv_status::no_timeout, wait());
+        EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+        EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+        EXPECT_EQ(RadioError::NONE, radioRsp_sim->rspInfo.error);
+
+        EXPECT_EQ(1, radioRsp_sim->carrierRestrictionsResp.allowedCarriers.size());
+        EXPECT_EQ(0, radioRsp_sim->carrierRestrictionsResp.excludedCarriers.size());
+        ASSERT_TRUE(std::string("123") ==
+                    radioRsp_sim->carrierRestrictionsResp.allowedCarriers[0].mcc);
+        ASSERT_TRUE(std::string("456") ==
+                    radioRsp_sim->carrierRestrictionsResp.allowedCarriers[0].mnc);
+        EXPECT_EQ(Carrier::MATCH_TYPE_ALL,
+                  radioRsp_sim->carrierRestrictionsResp.allowedCarriers[0].matchType);
+        ASSERT_TRUE(radioRsp_sim->carrierRestrictionsResp.allowedCarriersPrioritized);
+        EXPECT_EQ(SimLockMultiSimPolicy::NO_MULTISIM_POLICY, radioRsp_sim->multiSimPolicyResp);
+
+        sleep(10);
+
+        /**
+         * Another test case of the API to cover to allow carrier.
+         * If the API is supported, this is also used to reset to no carrier restriction
+         * status for cardStatus.
+         */
+        memset(&carrierRestrictions, 0, sizeof(carrierRestrictions));
+        carrierRestrictions.allowedCarriers.resize(0);
+        carrierRestrictions.excludedCarriers.resize(0);
+        carrierRestrictions.allowedCarriersPrioritized = false;
+
+        serial = GetRandomSerialNumber();
+        radio_sim->setAllowedCarriers(serial, carrierRestrictions, multisimPolicy);
+        EXPECT_EQ(std::cv_status::no_timeout, wait());
+        EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+        EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+
+        EXPECT_EQ(RadioError::NONE, radioRsp_sim->rspInfo.error);
+
+        if (cardStatus.cardState != CardStatus::STATE_ABSENT) {
+            /* Resetting back to no carrier restriction needs some time */
+            updateSimCardStatus();
+            auto startTime = std::chrono::system_clock::now();
+            while (cardStatus.cardState == CardStatus::STATE_RESTRICTED &&
+                   std::chrono::duration_cast<std::chrono::seconds>(
+                           std::chrono::system_clock::now() - startTime)
+                                   .count() < 10) {
+                /* Set 2 seconds as interval to check card status */
+                sleep(2);
+                updateSimCardStatus();
+            }
+            EXPECT_NE(CardStatus::STATE_RESTRICTED, cardStatus.cardState);
+            sleep(10);
+        }
+    }
+}
+
+/*
+ * Test IRadioSim.getIccCardStatus() for the response returned.
+ */
+TEST_P(RadioSimTest, getIccCardStatus) {
+    LOG(DEBUG) << "getIccCardStatus";
+    EXPECT_LE(cardStatus.applications.size(), RadioConst::CARD_MAX_APPS);
+    EXPECT_LT(cardStatus.gsmUmtsSubscriptionAppIndex, RadioConst::CARD_MAX_APPS);
+    EXPECT_LT(cardStatus.cdmaSubscriptionAppIndex, RadioConst::CARD_MAX_APPS);
+    EXPECT_LT(cardStatus.imsSubscriptionAppIndex, RadioConst::CARD_MAX_APPS);
+    LOG(DEBUG) << "getIccCardStatus finished";
+}
+
+/*
+ * Test IRadioSim.supplyIccPinForApp() for the response returned
+ */
+TEST_P(RadioSimTest, supplyIccPinForApp) {
+    LOG(DEBUG) << "supplyIccPinForApp";
+    serial = GetRandomSerialNumber();
+
+    // Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
+    // 3GPP2 apps only
+    for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
+        if (cardStatus.applications[i].appType == AppStatus::APP_TYPE_SIM ||
+            cardStatus.applications[i].appType == AppStatus::APP_TYPE_USIM ||
+            cardStatus.applications[i].appType == AppStatus::APP_TYPE_RUIM ||
+            cardStatus.applications[i].appType == AppStatus::APP_TYPE_CSIM) {
+            radio_sim->supplyIccPinForApp(serial, std::string("test1"),
+                                          cardStatus.applications[i].aidPtr);
+            EXPECT_EQ(std::cv_status::no_timeout, wait());
+            EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+            EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+            ASSERT_TRUE(CheckAnyOfErrors(
+                    radioRsp_sim->rspInfo.error,
+                    {RadioError::PASSWORD_INCORRECT, RadioError::REQUEST_NOT_SUPPORTED}));
+        }
+    }
+    LOG(DEBUG) << "supplyIccPinForApp finished";
+}
+
+/*
+ * Test IRadioSim.supplyIccPukForApp() for the response returned.
+ */
+TEST_P(RadioSimTest, supplyIccPukForApp) {
+    LOG(DEBUG) << "supplyIccPukForApp";
+    serial = GetRandomSerialNumber();
+
+    // Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
+    // 3GPP2 apps only
+    for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
+        if (cardStatus.applications[i].appType == AppStatus::APP_TYPE_SIM ||
+            cardStatus.applications[i].appType == AppStatus::APP_TYPE_USIM ||
+            cardStatus.applications[i].appType == AppStatus::APP_TYPE_RUIM ||
+            cardStatus.applications[i].appType == AppStatus::APP_TYPE_CSIM) {
+            radio_sim->supplyIccPukForApp(serial, std::string("test1"), std::string("test2"),
+                                          cardStatus.applications[i].aidPtr);
+            EXPECT_EQ(std::cv_status::no_timeout, wait());
+            EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+            EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+            ASSERT_TRUE(CheckAnyOfErrors(
+                    radioRsp_sim->rspInfo.error,
+                    {RadioError::PASSWORD_INCORRECT, RadioError::INVALID_SIM_STATE}));
+        }
+    }
+    LOG(DEBUG) << "supplyIccPukForApp finished";
+}
+
+/*
+ * Test IRadioSim.supplyIccPin2ForApp() for the response returned.
+ */
+TEST_P(RadioSimTest, supplyIccPin2ForApp) {
+    LOG(DEBUG) << "supplyIccPin2ForApp";
+    serial = GetRandomSerialNumber();
+
+    // Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
+    // 3GPP2 apps only
+    for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
+        if (cardStatus.applications[i].appType == AppStatus::APP_TYPE_SIM ||
+            cardStatus.applications[i].appType == AppStatus::APP_TYPE_USIM ||
+            cardStatus.applications[i].appType == AppStatus::APP_TYPE_RUIM ||
+            cardStatus.applications[i].appType == AppStatus::APP_TYPE_CSIM) {
+            radio_sim->supplyIccPin2ForApp(serial, std::string("test1"),
+                                           cardStatus.applications[i].aidPtr);
+            EXPECT_EQ(std::cv_status::no_timeout, wait());
+            EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+            EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+            ASSERT_TRUE(
+                    CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+                                     {RadioError::PASSWORD_INCORRECT,
+                                      RadioError::REQUEST_NOT_SUPPORTED, RadioError::SIM_PUK2}));
+        }
+    }
+    LOG(DEBUG) << "supplyIccPin2ForApp finished";
+}
+
+/*
+ * Test IRadioSim.supplyIccPuk2ForApp() for the response returned.
+ */
+TEST_P(RadioSimTest, supplyIccPuk2ForApp) {
+    LOG(DEBUG) << "supplyIccPuk2ForApp";
+    serial = GetRandomSerialNumber();
+
+    // Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
+    // 3GPP2 apps only
+    for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
+        if (cardStatus.applications[i].appType == AppStatus::APP_TYPE_SIM ||
+            cardStatus.applications[i].appType == AppStatus::APP_TYPE_USIM ||
+            cardStatus.applications[i].appType == AppStatus::APP_TYPE_RUIM ||
+            cardStatus.applications[i].appType == AppStatus::APP_TYPE_CSIM) {
+            radio_sim->supplyIccPuk2ForApp(serial, std::string("test1"), std::string("test2"),
+                                           cardStatus.applications[i].aidPtr);
+            EXPECT_EQ(std::cv_status::no_timeout, wait());
+            EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+            EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+            ASSERT_TRUE(CheckAnyOfErrors(
+                    radioRsp_sim->rspInfo.error,
+                    {RadioError::PASSWORD_INCORRECT, RadioError::INVALID_SIM_STATE}));
+        }
+    }
+    LOG(DEBUG) << "supplyIccPuk2ForApp finished";
+}
+
+/*
+ * Test IRadioSim.changeIccPinForApp() for the response returned.
+ */
+TEST_P(RadioSimTest, changeIccPinForApp) {
+    LOG(DEBUG) << "changeIccPinForApp";
+    serial = GetRandomSerialNumber();
+
+    // Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
+    // 3GPP2 apps only
+    for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
+        if (cardStatus.applications[i].appType == AppStatus::APP_TYPE_SIM ||
+            cardStatus.applications[i].appType == AppStatus::APP_TYPE_USIM ||
+            cardStatus.applications[i].appType == AppStatus::APP_TYPE_RUIM ||
+            cardStatus.applications[i].appType == AppStatus::APP_TYPE_CSIM) {
+            radio_sim->changeIccPinForApp(serial, std::string("test1"), std::string("test2"),
+                                          cardStatus.applications[i].aidPtr);
+            EXPECT_EQ(std::cv_status::no_timeout, wait());
+            EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+            EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+            ASSERT_TRUE(CheckAnyOfErrors(
+                    radioRsp_sim->rspInfo.error,
+                    {RadioError::PASSWORD_INCORRECT, RadioError::REQUEST_NOT_SUPPORTED}));
+        }
+    }
+    LOG(DEBUG) << "changeIccPinForApp finished";
+}
+
+/*
+ * Test IRadioSim.changeIccPin2ForApp() for the response returned.
+ */
+TEST_P(RadioSimTest, changeIccPin2ForApp) {
+    LOG(DEBUG) << "changeIccPin2ForApp";
+    serial = GetRandomSerialNumber();
+
+    // Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
+    // 3GPP2 apps only
+    for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
+        if (cardStatus.applications[i].appType == AppStatus::APP_TYPE_SIM ||
+            cardStatus.applications[i].appType == AppStatus::APP_TYPE_USIM ||
+            cardStatus.applications[i].appType == AppStatus::APP_TYPE_RUIM ||
+            cardStatus.applications[i].appType == AppStatus::APP_TYPE_CSIM) {
+            radio_sim->changeIccPin2ForApp(serial, std::string("test1"), std::string("test2"),
+                                           cardStatus.applications[i].aidPtr);
+            EXPECT_EQ(std::cv_status::no_timeout, wait());
+            EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+            EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+            ASSERT_TRUE(
+                    CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+                                     {RadioError::PASSWORD_INCORRECT,
+                                      RadioError::REQUEST_NOT_SUPPORTED, RadioError::SIM_PUK2}));
+        }
+    }
+    LOG(DEBUG) << "changeIccPin2ForApp finished";
+}
+
+/*
+ * Test IRadioSim.getImsiForApp() for the response returned.
+ */
+TEST_P(RadioSimTest, getImsiForApp) {
+    LOG(DEBUG) << "getImsiForApp";
+    serial = GetRandomSerialNumber();
+
+    // Check success returned while getting imsi for 3GPP and 3GPP2 apps only
+    for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
+        if (cardStatus.applications[i].appType == AppStatus::APP_TYPE_SIM ||
+            cardStatus.applications[i].appType == AppStatus::APP_TYPE_USIM ||
+            cardStatus.applications[i].appType == AppStatus::APP_TYPE_RUIM ||
+            cardStatus.applications[i].appType == AppStatus::APP_TYPE_CSIM) {
+            radio_sim->getImsiForApp(serial, cardStatus.applications[i].aidPtr);
+            EXPECT_EQ(std::cv_status::no_timeout, wait());
+            EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+            EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+            ASSERT_TRUE(CheckAnyOfErrors(radioRsp_sim->rspInfo.error, {RadioError::NONE},
+                                         CHECK_GENERAL_ERROR));
+
+            // IMSI (MCC+MNC+MSIN) is at least 6 digits, but not more than 15
+            if (radioRsp_sim->rspInfo.error == RadioError::NONE) {
+                EXPECT_NE(radioRsp_sim->imsi, std::string());
+                EXPECT_GE((int)(radioRsp_sim->imsi).size(), 6);
+                EXPECT_LE((int)(radioRsp_sim->imsi).size(), 15);
+            }
+        }
+    }
+    LOG(DEBUG) << "getImsiForApp finished";
+}
+
+/*
+ * Test IRadioSim.iccIoForApp() for the response returned.
+ */
+TEST_P(RadioSimTest, iccIoForApp) {
+    LOG(DEBUG) << "iccIoForApp";
+    serial = GetRandomSerialNumber();
+
+    for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
+        IccIo iccIo;
+        iccIo.command = 0xc0;
+        iccIo.fileId = 0x6f11;
+        iccIo.path = std::string("3F007FFF");
+        iccIo.p1 = 0;
+        iccIo.p2 = 0;
+        iccIo.p3 = 0;
+        iccIo.data = std::string();
+        iccIo.pin2 = std::string();
+        iccIo.aid = cardStatus.applications[i].aidPtr;
+
+        radio_sim->iccIoForApp(serial, iccIo);
+        EXPECT_EQ(std::cv_status::no_timeout, wait());
+        EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+        EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+    }
+    LOG(DEBUG) << "iccIoForApp finished";
+}
+
+/*
+ * Test IRadioSim.iccTransmitApduBasicChannel() for the response returned.
+ */
+TEST_P(RadioSimTest, iccTransmitApduBasicChannel) {
+    LOG(DEBUG) << "iccTransmitApduBasicChannel";
+    serial = GetRandomSerialNumber();
+    SimApdu msg;
+    memset(&msg, 0, sizeof(msg));
+    msg.data = std::string();
+
+    radio_sim->iccTransmitApduBasicChannel(serial, msg);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+    LOG(DEBUG) << "iccTransmitApduBasicChannel finished";
+}
+
+/*
+ * Test IRadioSim.iccOpenLogicalChannel() for the response returned.
+ */
+TEST_P(RadioSimTest, iccOpenLogicalChannel) {
+    LOG(DEBUG) << "iccOpenLogicalChannel";
+    serial = GetRandomSerialNumber();
+    int p2 = 0x04;
+    // Specified in ISO 7816-4 clause 7.1.1 0x04 means that FCP template is requested.
+    for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
+        radio_sim->iccOpenLogicalChannel(serial, cardStatus.applications[i].aidPtr, p2);
+        EXPECT_EQ(std::cv_status::no_timeout, wait());
+        EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+        EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    }
+    LOG(DEBUG) << "iccOpenLogicalChannel finished";
+}
+
+/*
+ * Test IRadioSim.iccCloseLogicalChannel() for the response returned.
+ */
+TEST_P(RadioSimTest, iccCloseLogicalChannel) {
+    LOG(DEBUG) << "iccCloseLogicalChannel";
+    serial = GetRandomSerialNumber();
+    // Try closing invalid channel and check INVALID_ARGUMENTS returned as error
+    radio_sim->iccCloseLogicalChannel(serial, 0);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+
+    EXPECT_EQ(RadioError::INVALID_ARGUMENTS, radioRsp_sim->rspInfo.error);
+    LOG(DEBUG) << "iccCloseLogicalChannel finished";
+}
+
+/*
+ * Test IRadioSim.iccTransmitApduLogicalChannel() for the response returned.
+ */
+TEST_P(RadioSimTest, iccTransmitApduLogicalChannel) {
+    LOG(DEBUG) << "iccTransmitApduLogicalChannel";
+    serial = GetRandomSerialNumber();
+    SimApdu msg;
+    memset(&msg, 0, sizeof(msg));
+    msg.data = std::string();
+
+    radio_sim->iccTransmitApduLogicalChannel(serial, msg);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+    LOG(DEBUG) << "iccTransmitApduLogicalChannel finished";
+}
+
+/*
+ * Test IRadioSim.requestIccSimAuthentication() for the response returned.
+ */
+TEST_P(RadioSimTest, requestIccSimAuthentication) {
+    LOG(DEBUG) << "requestIccSimAuthentication";
+    serial = GetRandomSerialNumber();
+
+    // Pass wrong challenge string and check RadioError::INVALID_ARGUMENTS
+    // or REQUEST_NOT_SUPPORTED returned as error.
+    for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
+        radio_sim->requestIccSimAuthentication(serial, 0, std::string("test"),
+                                               cardStatus.applications[i].aidPtr);
+        EXPECT_EQ(std::cv_status::no_timeout, wait());
+        EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+        EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_sim->rspInfo.error,
+                {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+    }
+    LOG(DEBUG) << "requestIccSimAuthentication finished";
+}
+
+/*
+ * Test IRadioSim.getFacilityLockForApp() for the response returned.
+ */
+TEST_P(RadioSimTest, getFacilityLockForApp) {
+    serial = GetRandomSerialNumber();
+    std::string facility = "";
+    std::string password = "";
+    int32_t serviceClass = 1;
+    std::string appId = "";
+
+    radio_sim->getFacilityLockForApp(serial, facility, password, serviceClass, appId);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+                                     {RadioError::INVALID_ARGUMENTS, RadioError::MODEM_ERR},
+                                     CHECK_GENERAL_ERROR));
+    }
+}
+
+/*
+ * Test IRadioSim.setFacilityLockForApp() for the response returned.
+ */
+TEST_P(RadioSimTest, setFacilityLockForApp) {
+    serial = GetRandomSerialNumber();
+    std::string facility = "";
+    bool lockState = false;
+    std::string password = "";
+    int32_t serviceClass = 1;
+    std::string appId = "";
+
+    radio_sim->setFacilityLockForApp(serial, facility, lockState, password, serviceClass, appId);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+                                     {RadioError::INVALID_ARGUMENTS, RadioError::MODEM_ERR},
+                                     CHECK_GENERAL_ERROR));
+    }
+}
+
+/*
+ * Test IRadioSim.getCdmaSubscription() for the response returned.
+ */
+TEST_P(RadioSimTest, getCdmaSubscription) {
+    LOG(DEBUG) << "getCdmaSubscription";
+    serial = GetRandomSerialNumber();
+
+    radio_sim->getCdmaSubscription(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_sim->rspInfo.error,
+                {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED, RadioError::SIM_ABSENT}));
+    }
+    LOG(DEBUG) << "getCdmaSubscription finished";
+}
+
+/*
+ * Test IRadioSim.getCdmaSubscriptionSource() for the response returned.
+ */
+TEST_P(RadioSimTest, getCdmaSubscriptionSource) {
+    LOG(DEBUG) << "getCdmaSubscriptionSource";
+    serial = GetRandomSerialNumber();
+
+    radio_sim->getCdmaSubscriptionSource(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_sim->rspInfo.error,
+                {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED, RadioError::SIM_ABSENT}));
+    }
+    LOG(DEBUG) << "getCdmaSubscriptionSource finished";
+}
+
+/*
+ * Test IRadioSim.setCdmaSubscriptionSource() for the response returned.
+ */
+TEST_P(RadioSimTest, setCdmaSubscriptionSource) {
+    LOG(DEBUG) << "setCdmaSubscriptionSource";
+    serial = GetRandomSerialNumber();
+
+    radio_sim->setCdmaSubscriptionSource(serial, CdmaSubscriptionSource::RUIM_SIM);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_sim->rspInfo.error,
+                {RadioError::NONE, RadioError::SIM_ABSENT, RadioError::SUBSCRIPTION_NOT_AVAILABLE},
+                CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "setCdmaSubscriptionSource finished";
+}
+
+/*
+ * Test IRadioSim.setUiccSubscription() for the response returned.
+ */
+TEST_P(RadioSimTest, setUiccSubscription) {
+    LOG(DEBUG) << "setUiccSubscription";
+    serial = GetRandomSerialNumber();
+    SelectUiccSub item;
+    memset(&item, 0, sizeof(item));
+
+    radio_sim->setUiccSubscription(serial, item);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(
+                CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+                                 {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
+                                  RadioError::MODEM_ERR, RadioError::SUBSCRIPTION_NOT_SUPPORTED},
+                                 CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "setUiccSubscription finished";
+}
+
+/*
+ * Test IRadioSim.sendEnvelope() for the response returned.
+ */
+TEST_P(RadioSimTest, sendEnvelope) {
+    LOG(DEBUG) << "sendEnvelope";
+    serial = GetRandomSerialNumber();
+
+    // Test with sending empty string
+    std::string content = "";
+
+    radio_sim->sendEnvelope(serial, content);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_sim->rspInfo.error,
+                                     {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
+                                      RadioError::MODEM_ERR, RadioError::SIM_ABSENT},
+                                     CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "sendEnvelope finished";
+}
+
+/*
+ * Test IRadioSim.sendTerminalResponseToSim() for the response returned.
+ */
+TEST_P(RadioSimTest, sendTerminalResponseToSim) {
+    LOG(DEBUG) << "sendTerminalResponseToSim";
+    serial = GetRandomSerialNumber();
+
+    // Test with sending empty string
+    std::string commandResponse = "";
+
+    radio_sim->sendTerminalResponseToSim(serial, commandResponse);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_sim->rspInfo.error,
+                {RadioError::NONE, RadioError::INVALID_ARGUMENTS, RadioError::SIM_ABSENT},
+                CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "sendTerminalResponseToSim finished";
+}
+
+/*
+ * Test IRadioSim.reportStkServiceIsRunning() for the response returned.
+ */
+TEST_P(RadioSimTest, reportStkServiceIsRunning) {
+    LOG(DEBUG) << "reportStkServiceIsRunning";
+    serial = GetRandomSerialNumber();
+
+    radio_sim->reportStkServiceIsRunning(serial);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_sim->rspInfo.error, {RadioError::NONE},
+                                     CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "reportStkServiceIsRunning finished";
+}
+
+/*
+ * Test IRadioSim.sendEnvelopeWithStatus() for the response returned with empty
+ * string.
+ */
+TEST_P(RadioSimTest, sendEnvelopeWithStatus) {
+    LOG(DEBUG) << "sendEnvelopeWithStatus";
+    serial = GetRandomSerialNumber();
+
+    // Test with sending empty string
+    std::string contents = "";
+
+    radio_sim->sendEnvelopeWithStatus(serial, contents);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_sim->rspInfo.error,
+                {RadioError::INVALID_ARGUMENTS, RadioError::MODEM_ERR, RadioError::SIM_ABSENT},
+                CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "sendEnvelopeWithStatus finished";
+}
diff --git a/radio/aidl/vts/radio_sim_utils.h b/radio/aidl/vts/radio_sim_utils.h
new file mode 100644
index 0000000..83f1cbc
--- /dev/null
+++ b/radio/aidl/vts/radio_sim_utils.h
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/radio/sim/BnRadioSimIndication.h>
+#include <aidl/android/hardware/radio/sim/BnRadioSimResponse.h>
+#include <aidl/android/hardware/radio/sim/IRadioSim.h>
+
+#include "radio_aidl_hal_utils.h"
+
+using namespace aidl::android::hardware::radio::sim;
+
+class RadioSimTest;
+
+/* Callback class for radio SIM response */
+class RadioSimResponse : public BnRadioSimResponse {
+  protected:
+    RadioServiceTest& parent_sim;
+
+  public:
+    RadioSimResponse(RadioServiceTest& parent_sim);
+    virtual ~RadioSimResponse() = default;
+
+    RadioResponseInfo rspInfo;
+    CarrierRestrictions carrierRestrictionsResp;
+    SimLockMultiSimPolicy multiSimPolicyResp;
+    bool canToggleUiccApplicationsEnablement;
+    bool areUiccApplicationsEnabled;
+    PhonebookCapacity capacity;
+    int32_t updatedRecordIndex;
+    std::string imsi;
+
+    virtual ndk::ScopedAStatus acknowledgeRequest(int32_t serial) override;
+
+    virtual ndk::ScopedAStatus areUiccApplicationsEnabledResponse(const RadioResponseInfo& info,
+                                                                  bool enabled) override;
+
+    virtual ndk::ScopedAStatus changeIccPin2ForAppResponse(const RadioResponseInfo& info,
+                                                           int32_t remainingRetries) override;
+
+    virtual ndk::ScopedAStatus changeIccPinForAppResponse(const RadioResponseInfo& info,
+                                                          int32_t remainingRetries) override;
+
+    virtual ndk::ScopedAStatus enableUiccApplicationsResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus getAllowedCarriersResponse(
+            const RadioResponseInfo& info, const CarrierRestrictions& carriers,
+            const SimLockMultiSimPolicy multiSimPolicy) override;
+
+    virtual ndk::ScopedAStatus getCdmaSubscriptionResponse(
+            const RadioResponseInfo& info, const std::string& mdn, const std::string& hSid,
+            const std::string& hNid, const std::string& min, const std::string& prl) override;
+
+    virtual ndk::ScopedAStatus getCdmaSubscriptionSourceResponse(
+            const RadioResponseInfo& info, CdmaSubscriptionSource source) override;
+
+    virtual ndk::ScopedAStatus getFacilityLockForAppResponse(const RadioResponseInfo& info,
+                                                             int32_t response) override;
+
+    virtual ndk::ScopedAStatus getIccCardStatusResponse(const RadioResponseInfo& info,
+                                                        const CardStatus& cardStatus) override;
+
+    virtual ndk::ScopedAStatus getImsiForAppResponse(const RadioResponseInfo& info,
+                                                     const std::string& imsi) override;
+
+    virtual ndk::ScopedAStatus getSimPhonebookCapacityResponse(
+            const RadioResponseInfo& info, const PhonebookCapacity& capacity) override;
+
+    virtual ndk::ScopedAStatus getSimPhonebookRecordsResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus iccCloseLogicalChannelResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus iccIoForAppResponse(const RadioResponseInfo& info,
+                                                   const IccIoResult& iccIo) override;
+
+    virtual ndk::ScopedAStatus iccOpenLogicalChannelResponse(
+            const RadioResponseInfo& info, int32_t channelId,
+            const std::vector<uint8_t>& selectResponse) override;
+
+    virtual ndk::ScopedAStatus iccTransmitApduBasicChannelResponse(
+            const RadioResponseInfo& info, const IccIoResult& result) override;
+
+    virtual ndk::ScopedAStatus iccTransmitApduLogicalChannelResponse(
+            const RadioResponseInfo& info, const IccIoResult& result) override;
+
+    virtual ndk::ScopedAStatus reportStkServiceIsRunningResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus requestIccSimAuthenticationResponse(
+            const RadioResponseInfo& info, const IccIoResult& result) override;
+
+    virtual ndk::ScopedAStatus sendEnvelopeResponse(const RadioResponseInfo& info,
+                                                    const std::string& commandResponse) override;
+
+    virtual ndk::ScopedAStatus sendEnvelopeWithStatusResponse(const RadioResponseInfo& info,
+                                                              const IccIoResult& iccIo) override;
+
+    virtual ndk::ScopedAStatus sendTerminalResponseToSimResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setAllowedCarriersResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setCarrierInfoForImsiEncryptionResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setCdmaSubscriptionSourceResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setFacilityLockForAppResponse(const RadioResponseInfo& info,
+                                                             int32_t retry) override;
+
+    virtual ndk::ScopedAStatus setSimCardPowerResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setUiccSubscriptionResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus supplyIccPin2ForAppResponse(const RadioResponseInfo& info,
+                                                           int32_t remainingRetries) override;
+
+    virtual ndk::ScopedAStatus supplyIccPinForAppResponse(const RadioResponseInfo& info,
+                                                          int32_t remainingRetries) override;
+
+    virtual ndk::ScopedAStatus supplyIccPuk2ForAppResponse(const RadioResponseInfo& info,
+                                                           int32_t remainingRetries) override;
+
+    virtual ndk::ScopedAStatus supplyIccPukForAppResponse(const RadioResponseInfo& info,
+                                                          int32_t remainingRetries) override;
+
+    virtual ndk::ScopedAStatus supplySimDepersonalizationResponse(
+            const RadioResponseInfo& info, PersoSubstate persoType,
+            int32_t remainingRetries) override;
+
+    virtual ndk::ScopedAStatus updateSimPhonebookRecordsResponse(
+            const RadioResponseInfo& info, int32_t updatedRecordIndex) override;
+};
+
+/* Callback class for radio SIM indication */
+class RadioSimIndication : public BnRadioSimIndication {
+  protected:
+    RadioServiceTest& parent_sim;
+
+  public:
+    RadioSimIndication(RadioServiceTest& parent_sim);
+    virtual ~RadioSimIndication() = default;
+
+    virtual ndk::ScopedAStatus carrierInfoForImsiEncryption(RadioIndicationType info) override;
+
+    virtual ndk::ScopedAStatus cdmaSubscriptionSourceChanged(
+            RadioIndicationType type, CdmaSubscriptionSource cdmaSource) override;
+
+    virtual ndk::ScopedAStatus simPhonebookChanged(RadioIndicationType type) override;
+
+    virtual ndk::ScopedAStatus simPhonebookRecordsReceived(
+            RadioIndicationType type, PbReceivedStatus status,
+            const std::vector<PhonebookRecordInfo>& records) override;
+
+    virtual ndk::ScopedAStatus simRefresh(RadioIndicationType type,
+                                          const SimRefreshResult& refreshResult) override;
+
+    virtual ndk::ScopedAStatus simStatusChanged(RadioIndicationType type) override;
+
+    virtual ndk::ScopedAStatus stkEventNotify(RadioIndicationType type,
+                                              const std::string& cmd) override;
+
+    virtual ndk::ScopedAStatus stkProactiveCommand(RadioIndicationType type,
+                                                   const std::string& cmd) override;
+
+    virtual ndk::ScopedAStatus stkSessionEnd(RadioIndicationType type) override;
+
+    virtual ndk::ScopedAStatus subscriptionStatusChanged(RadioIndicationType type,
+                                                         bool activate) override;
+
+    virtual ndk::ScopedAStatus uiccApplicationsEnablementChanged(RadioIndicationType type,
+                                                                 bool enabled) override;
+};
+
+// The main test class for Radio AIDL SIM.
+class RadioSimTest : public ::testing::TestWithParam<std::string>, public RadioServiceTest {
+  public:
+    virtual void SetUp() override;
+
+    /* Override updateSimCardStatus in RadioServiceTest to not call setResponseFunctions */
+    void updateSimCardStatus();
+
+    /* radio SIM service handle in RadioServiceTest */
+    /* radio SIM response handle */
+    std::shared_ptr<RadioSimResponse> radioRsp_sim;
+    /* radio SIM indication handle */
+    std::shared_ptr<RadioSimIndication> radioInd_sim;
+};
diff --git a/radio/aidl/vts/radio_voice_indication.cpp b/radio/aidl/vts/radio_voice_indication.cpp
new file mode 100644
index 0000000..3fee326
--- /dev/null
+++ b/radio/aidl/vts/radio_voice_indication.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "radio_voice_utils.h"
+
+RadioVoiceIndication::RadioVoiceIndication(RadioServiceTest& parent) : parent_voice(parent) {}
+
+ndk::ScopedAStatus RadioVoiceIndication::callRing(RadioIndicationType /*type*/, bool /*isGsm*/,
+                                                  const CdmaSignalInfoRecord& /*record*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::callStateChanged(RadioIndicationType /*type*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::cdmaCallWaiting(
+        RadioIndicationType /*type*/, const CdmaCallWaiting& /*callWaitingRecord*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::cdmaInfoRec(
+        RadioIndicationType /*type*/, const std::vector<CdmaInformationRecord>& /*records*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::cdmaOtaProvisionStatus(RadioIndicationType /*type*/,
+                                                                CdmaOtaProvisionStatus /*status*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::currentEmergencyNumberList(
+        RadioIndicationType /*type*/, const std::vector<EmergencyNumber>& /*emergencyNumberList*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::enterEmergencyCallbackMode(RadioIndicationType /*type*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::exitEmergencyCallbackMode(RadioIndicationType /*type*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::indicateRingbackTone(RadioIndicationType /*type*/,
+                                                              bool /*start*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::onSupplementaryServiceIndication(
+        RadioIndicationType /*type*/, const StkCcUnsolSsResult& /*ss*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::onUssd(RadioIndicationType /*type*/,
+                                                UssdModeType /*modeType*/,
+                                                const std::string& /*msg*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::resendIncallMute(RadioIndicationType /*type*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::srvccStateNotify(RadioIndicationType /*type*/,
+                                                          SrvccState /*state*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::stkCallControlAlphaNotify(RadioIndicationType /*type*/,
+                                                                   const std::string& /*alpha*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceIndication::stkCallSetup(RadioIndicationType /*type*/,
+                                                      int64_t /*timeout*/) {
+    return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_voice_response.cpp b/radio/aidl/vts/radio_voice_response.cpp
new file mode 100644
index 0000000..dd7b1bf
--- /dev/null
+++ b/radio/aidl/vts/radio_voice_response.cpp
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "radio_voice_utils.h"
+
+RadioVoiceResponse::RadioVoiceResponse(RadioServiceTest& parent) : parent_voice(parent) {}
+
+ndk::ScopedAStatus RadioVoiceResponse::acceptCallResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::acknowledgeRequest(int32_t /*serial*/) {
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::cancelPendingUssdResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::conferenceResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::dialResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::emergencyDialResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::exitEmergencyCallbackModeResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::explicitCallTransferResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::getCallForwardStatusResponse(
+        const RadioResponseInfo& info, const std::vector<CallForwardInfo>& /*callForwardInfos*/) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::getCallWaitingResponse(const RadioResponseInfo& info,
+                                                              bool /*enable*/,
+                                                              int32_t /*serviceClass*/) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::getClipResponse(const RadioResponseInfo& info,
+                                                       ClipStatus /*status*/) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::getClirResponse(const RadioResponseInfo& info, int32_t /*n*/,
+                                                       int32_t /*m*/) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::getCurrentCallsResponse(const RadioResponseInfo& info,
+                                                               const std::vector<Call>& calls) {
+    rspInfo = info;
+    currentCalls = calls;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::getLastCallFailCauseResponse(
+        const RadioResponseInfo& info, const LastCallFailCauseInfo& /*failCauseInfo*/) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::getMuteResponse(const RadioResponseInfo& info,
+                                                       bool /*enable*/) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::getPreferredVoicePrivacyResponse(
+        const RadioResponseInfo& info, bool /*enable*/) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::getTtyModeResponse(const RadioResponseInfo& info,
+                                                          TtyMode /*mode*/) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::handleStkCallSetupRequestFromSimResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::hangupConnectionResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::hangupForegroundResumeBackgroundResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::hangupWaitingOrBackgroundResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::isVoNrEnabledResponse(const RadioResponseInfo& info,
+                                                             bool /*enabled*/) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::rejectCallResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::sendBurstDtmfResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::sendCdmaFeatureCodeResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::sendDtmfResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::sendUssdResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::separateConnectionResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::setCallForwardResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::setCallWaitingResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::setClirResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::setMuteResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::setPreferredVoicePrivacyResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::setTtyModeResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::setVoNrEnabledResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::startDtmfResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::stopDtmfResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioVoiceResponse::switchWaitingOrHoldingAndActiveResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_voice.notify(info.serial);
+    return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_voice_test.cpp b/radio/aidl/vts/radio_voice_test.cpp
new file mode 100644
index 0000000..249ee63
--- /dev/null
+++ b/radio/aidl/vts/radio_voice_test.cpp
@@ -0,0 +1,979 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aidl/android/hardware/radio/config/IRadioConfig.h>
+#include <aidl/android/hardware/radio/voice/EmergencyServiceCategory.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+
+#include "radio_voice_utils.h"
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
+
+void RadioVoiceTest::SetUp() {
+    std::string serviceName = GetParam();
+
+    if (!isServiceValidForDeviceConfiguration(serviceName)) {
+        ALOGI("Skipped the test due to device configuration.");
+        GTEST_SKIP();
+    }
+
+    radio_voice = IRadioVoice::fromBinder(
+            ndk::SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+    ASSERT_NE(nullptr, radio_voice.get());
+
+    radioRsp_voice = ndk::SharedRefBase::make<RadioVoiceResponse>(*this);
+    ASSERT_NE(nullptr, radioRsp_voice.get());
+
+    count_ = 0;
+
+    radioInd_voice = ndk::SharedRefBase::make<RadioVoiceIndication>(*this);
+    ASSERT_NE(nullptr, radioInd_voice.get());
+
+    radio_voice->setResponseFunctions(radioRsp_voice, radioInd_voice);
+
+    // Assert IRadioSim exists and SIM is present before testing
+    radio_sim = sim::IRadioSim::fromBinder(ndk::SpAIBinder(
+            AServiceManager_waitForService("android.hardware.radio.sim.IRadioSim/slot1")));
+    ASSERT_NE(nullptr, radio_sim.get());
+    updateSimCardStatus();
+    EXPECT_EQ(CardStatus::STATE_PRESENT, cardStatus.cardState);
+
+    // Assert IRadioConfig exists before testing
+    radio_config = config::IRadioConfig::fromBinder(ndk::SpAIBinder(
+            AServiceManager_waitForService("android.hardware.radio.config.IRadioConfig/default")));
+    ASSERT_NE(nullptr, radio_config.get());
+
+    if (isDsDsEnabled() || isTsTsEnabled()) {
+        radio_network = IRadioNetwork::fromBinder(ndk::SpAIBinder(AServiceManager_waitForService(
+                "android.hardware.radio.network.IRadioNetwork/slot1")));
+        ASSERT_NE(nullptr, radio_network.get());
+        radioRsp_network = ndk::SharedRefBase::make<RadioNetworkResponse>(*this);
+        radioInd_network = ndk::SharedRefBase::make<RadioNetworkIndication>(*this);
+        radio_network->setResponseFunctions(radioRsp_network, radioInd_network);
+    }
+}
+
+ndk::ScopedAStatus RadioVoiceTest::clearPotentialEstablishedCalls() {
+    // Get the current call Id to hangup the established emergency call.
+    serial = GetRandomSerialNumber();
+    radio_voice->getCurrentCalls(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+
+    // Hang up to disconnect the established call channels.
+    for (const Call& call : radioRsp_voice->currentCalls) {
+        serial = GetRandomSerialNumber();
+        radio_voice->hangup(serial, call.index);
+        ALOGI("Hang up to disconnect the established call channel: %d", call.index);
+        EXPECT_EQ(std::cv_status::no_timeout, wait());
+        // Give some time for modem to disconnect the established call channel.
+        sleep(MODEM_EMERGENCY_CALL_DISCONNECT_TIME);
+    }
+
+    // Verify there are no more current calls.
+    serial = GetRandomSerialNumber();
+    radio_voice->getCurrentCalls(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(0, radioRsp_voice->currentCalls.size());
+    return ndk::ScopedAStatus::ok();
+}
+
+/*
+ * Test IRadioVoice.emergencyDial() for the response returned.
+ */
+TEST_P(RadioVoiceTest, emergencyDial) {
+    if (!deviceSupportsFeature(FEATURE_VOICE_CALL)) {
+        ALOGI("Skipping emergencyDial because voice call is not supported in device");
+        return;
+    } else if (!deviceSupportsFeature(FEATURE_TELEPHONY_GSM) &&
+               !deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
+        ALOGI("Skipping emergencyDial because gsm/cdma radio is not supported in device");
+        return;
+    } else {
+        ALOGI("Running emergencyDial because voice call is supported in device");
+    }
+
+    serial = GetRandomSerialNumber();
+
+    Dial dialInfo;
+    dialInfo.address = std::string("911");
+    int32_t categories = static_cast<int32_t>(EmergencyServiceCategory::UNSPECIFIED);
+    std::vector<std::string> urns = {""};
+    EmergencyCallRouting routing = EmergencyCallRouting::UNKNOWN;
+
+    ndk::ScopedAStatus res =
+            radio_voice->emergencyDial(serial, dialInfo, categories, urns, routing, true, true);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    ALOGI("emergencyDial, rspInfo.error = %s\n", toString(radioRsp_voice->rspInfo.error).c_str());
+
+    RadioError rspEmergencyDial = radioRsp_voice->rspInfo.error;
+    // In DSDS or TSTS, we only check the result if the current slot is IN_SERVICE
+    // or Emergency_Only.
+    if (isDsDsEnabled() || isTsTsEnabled()) {
+        serial = GetRandomSerialNumber();
+        radio_network->getVoiceRegistrationState(serial);
+        EXPECT_EQ(std::cv_status::no_timeout, wait());
+        if (isVoiceEmergencyOnly(radioRsp_network->voiceRegResp.regState) ||
+            isVoiceInService(radioRsp_network->voiceRegResp.regState)) {
+            EXPECT_EQ(RadioError::NONE, rspEmergencyDial);
+        }
+    } else {
+        EXPECT_EQ(RadioError::NONE, rspEmergencyDial);
+    }
+
+    // Give some time for modem to establish the emergency call channel.
+    sleep(MODEM_EMERGENCY_CALL_ESTABLISH_TIME);
+
+    // Disconnect all the potential established calls to prevent them affecting other tests.
+    clearPotentialEstablishedCalls();
+}
+
+/*
+ * Test IRadioVoice.emergencyDial() with specified service and its response returned.
+ */
+TEST_P(RadioVoiceTest, emergencyDial_withServices) {
+    if (!deviceSupportsFeature(FEATURE_VOICE_CALL)) {
+        ALOGI("Skipping emergencyDial because voice call is not supported in device");
+        return;
+    } else if (!deviceSupportsFeature(FEATURE_TELEPHONY_GSM) &&
+               !deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
+        ALOGI("Skipping emergencyDial because gsm/cdma radio is not supported in device");
+        return;
+    } else {
+        ALOGI("Running emergencyDial because voice call is supported in device");
+    }
+
+    serial = GetRandomSerialNumber();
+
+    Dial dialInfo;
+    dialInfo.address = std::string("911");
+    int32_t categories = static_cast<int32_t>(EmergencyServiceCategory::AMBULANCE);
+    std::vector<std::string> urns = {"urn:service:sos.ambulance"};
+    EmergencyCallRouting routing = EmergencyCallRouting::UNKNOWN;
+
+    ndk::ScopedAStatus res =
+            radio_voice->emergencyDial(serial, dialInfo, categories, urns, routing, true, true);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    ALOGI("emergencyDial_withServices, rspInfo.error = %s\n",
+          toString(radioRsp_voice->rspInfo.error).c_str());
+    RadioError rspEmergencyDial = radioRsp_voice->rspInfo.error;
+
+    // In DSDS or TSTS, we only check the result if the current slot is IN_SERVICE
+    // or Emergency_Only.
+    if (isDsDsEnabled() || isTsTsEnabled()) {
+        serial = GetRandomSerialNumber();
+        radio_network->getVoiceRegistrationState(serial);
+        EXPECT_EQ(std::cv_status::no_timeout, wait());
+        if (isVoiceEmergencyOnly(radioRsp_network->voiceRegResp.regState) ||
+            isVoiceInService(radioRsp_network->voiceRegResp.regState)) {
+            EXPECT_EQ(RadioError::NONE, rspEmergencyDial);
+        }
+    } else {
+        EXPECT_EQ(RadioError::NONE, rspEmergencyDial);
+    }
+    // Give some time for modem to establish the emergency call channel.
+    sleep(MODEM_EMERGENCY_CALL_ESTABLISH_TIME);
+
+    // Disconnect all the potential established calls to prevent them affecting other tests.
+    clearPotentialEstablishedCalls();
+}
+
+/*
+ * Test IRadioVoice.emergencyDial() with known emergency call routing and its response returned.
+ */
+TEST_P(RadioVoiceTest, emergencyDial_withEmergencyRouting) {
+    if (!deviceSupportsFeature(FEATURE_VOICE_CALL)) {
+        ALOGI("Skipping emergencyDial because voice call is not supported in device");
+        return;
+    } else if (!deviceSupportsFeature(FEATURE_TELEPHONY_GSM) &&
+               !deviceSupportsFeature(FEATURE_TELEPHONY_CDMA)) {
+        ALOGI("Skipping emergencyDial because gsm/cdma radio is not supported in device");
+        return;
+    } else {
+        ALOGI("Running emergencyDial because voice call is supported in device");
+    }
+
+    serial = GetRandomSerialNumber();
+
+    Dial dialInfo;
+    dialInfo.address = std::string("911");
+    int32_t categories = static_cast<int32_t>(EmergencyServiceCategory::UNSPECIFIED);
+    std::vector<std::string> urns = {""};
+    EmergencyCallRouting routing = EmergencyCallRouting::EMERGENCY;
+
+    ndk::ScopedAStatus res =
+            radio_voice->emergencyDial(serial, dialInfo, categories, urns, routing, true, true);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    ALOGI("emergencyDial_withEmergencyRouting, rspInfo.error = %s\n",
+          toString(radioRsp_voice->rspInfo.error).c_str());
+    RadioError rspEmergencyDial = radioRsp_voice->rspInfo.error;
+
+    // In DSDS or TSTS, we only check the result if the current slot is IN_SERVICE
+    // or Emergency_Only.
+    if (isDsDsEnabled() || isTsTsEnabled()) {
+        serial = GetRandomSerialNumber();
+        radio_network->getVoiceRegistrationState(serial);
+        EXPECT_EQ(std::cv_status::no_timeout, wait());
+        if (isVoiceEmergencyOnly(radioRsp_network->voiceRegResp.regState) ||
+            isVoiceInService(radioRsp_network->voiceRegResp.regState)) {
+            EXPECT_EQ(RadioError::NONE, rspEmergencyDial);
+        }
+    } else {
+        EXPECT_EQ(RadioError::NONE, rspEmergencyDial);
+    }
+
+    // Give some time for modem to establish the emergency call channel.
+    sleep(MODEM_EMERGENCY_CALL_ESTABLISH_TIME);
+
+    // Disconnect all the potential established calls to prevent them affecting other tests.
+    clearPotentialEstablishedCalls();
+}
+
+/*
+ * Test IRadioVoice.getCurrentCalls() for the response returned.
+ */
+TEST_P(RadioVoiceTest, getCurrentCalls) {
+    serial = GetRandomSerialNumber();
+    radio_voice->getCurrentCalls(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+    EXPECT_EQ(RadioError::NONE, radioRsp_voice->rspInfo.error);
+}
+
+/*
+ * Test IRadioVoice.getClir() for the response returned.
+ */
+TEST_P(RadioVoiceTest, getClir) {
+    serial = GetRandomSerialNumber();
+
+    radio_voice->getClir(serial);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error, {RadioError::MODEM_ERR},
+                                     CHECK_GENERAL_ERROR));
+    }
+}
+
+/*
+ * Test IRadioVoice.setClir() for the response returned.
+ */
+TEST_P(RadioVoiceTest, setClir) {
+    serial = GetRandomSerialNumber();
+    int32_t status = 1;
+
+    radio_voice->setClir(serial, status);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        EXPECT_EQ(RadioError::NONE, radioRsp_voice->rspInfo.error);
+    }
+}
+
+/*
+ * Test IRadioVoice.getClip() for the response returned.
+ */
+TEST_P(RadioVoiceTest, getClip) {
+    serial = GetRandomSerialNumber();
+
+    radio_voice->getClip(serial);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error, {RadioError::MODEM_ERR},
+                                     CHECK_GENERAL_ERROR));
+    }
+}
+
+/*
+ * Test IRadioVoice.getTtyMode() for the response returned.
+ */
+TEST_P(RadioVoiceTest, getTtyMode) {
+    LOG(DEBUG) << "getTtyMode";
+    serial = GetRandomSerialNumber();
+
+    radio_voice->getTtyMode(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        EXPECT_EQ(RadioError::NONE, radioRsp_voice->rspInfo.error);
+    }
+    LOG(DEBUG) << "getTtyMode finished";
+}
+
+/*
+ * Test IRadioVoice.setTtyMode() for the response returned.
+ */
+TEST_P(RadioVoiceTest, setTtyMode) {
+    LOG(DEBUG) << "setTtyMode";
+    serial = GetRandomSerialNumber();
+
+    radio_voice->setTtyMode(serial, TtyMode::OFF);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        EXPECT_EQ(RadioError::NONE, radioRsp_voice->rspInfo.error);
+    }
+    LOG(DEBUG) << "setTtyMode finished";
+}
+
+/*
+ * Test IRadioVoice.setPreferredVoicePrivacy() for the response returned.
+ */
+TEST_P(RadioVoiceTest, setPreferredVoicePrivacy) {
+    LOG(DEBUG) << "setPreferredVoicePrivacy";
+    serial = GetRandomSerialNumber();
+
+    radio_voice->setPreferredVoicePrivacy(serial, true);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
+                                     {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+    }
+    LOG(DEBUG) << "setPreferredVoicePrivacy finished";
+}
+
+/*
+ * Test IRadioVoice.getPreferredVoicePrivacy() for the response returned.
+ */
+TEST_P(RadioVoiceTest, getPreferredVoicePrivacy) {
+    LOG(DEBUG) << "getPreferredVoicePrivacy";
+    serial = GetRandomSerialNumber();
+
+    radio_voice->getPreferredVoicePrivacy(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
+                                     {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+    }
+    LOG(DEBUG) << "getPreferredVoicePrivacy finished";
+}
+
+/*
+ * Test IRadioVoice.exitEmergencyCallbackMode() for the response returned.
+ */
+TEST_P(RadioVoiceTest, exitEmergencyCallbackMode) {
+    LOG(DEBUG) << "exitEmergencyCallbackMode";
+    serial = GetRandomSerialNumber();
+
+    radio_voice->exitEmergencyCallbackMode(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_voice->rspInfo.error,
+                {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED, RadioError::SIM_ABSENT}));
+    }
+    LOG(DEBUG) << "exitEmergencyCallbackMode finished";
+}
+
+/*
+ * Test IRadioVoice.handleStkCallSetupRequestFromSim() for the response returned.
+ */
+TEST_P(RadioVoiceTest, handleStkCallSetupRequestFromSim) {
+    LOG(DEBUG) << "handleStkCallSetupRequestFromSim";
+    serial = GetRandomSerialNumber();
+    bool accept = false;
+
+    radio_voice->handleStkCallSetupRequestFromSim(serial, accept);
+
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
+                                     {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
+                                      RadioError::MODEM_ERR, RadioError::SIM_ABSENT},
+                                     CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "handleStkCallSetupRequestFromSim finished";
+}
+
+/*
+ * Test IRadioVoice.dial() for the response returned.
+ */
+TEST_P(RadioVoiceTest, dial) {
+    LOG(DEBUG) << "dial";
+    serial = GetRandomSerialNumber();
+
+    Dial dialInfo;
+    memset(&dialInfo, 0, sizeof(dialInfo));
+    dialInfo.address = std::string("123456789");
+
+    radio_voice->dial(serial, dialInfo);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_voice->rspInfo.error,
+                {RadioError::CANCELLED, RadioError::DEVICE_IN_USE, RadioError::FDN_CHECK_FAILURE,
+                 RadioError::INVALID_ARGUMENTS, RadioError::INVALID_CALL_ID,
+                 RadioError::INVALID_MODEM_STATE, RadioError::INVALID_STATE, RadioError::MODEM_ERR,
+                 RadioError::NO_NETWORK_FOUND, RadioError::NO_SUBSCRIPTION,
+                 RadioError::OPERATION_NOT_ALLOWED},
+                CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "dial finished";
+}
+
+/*
+ * Test IRadioVoice.hangup() for the response returned.
+ */
+TEST_P(RadioVoiceTest, hangup) {
+    LOG(DEBUG) << "hangup";
+    serial = GetRandomSerialNumber();
+
+    radio_voice->hangup(serial, 1);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_voice->rspInfo.error,
+                {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+                CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "hangup finished";
+}
+
+/*
+ * Test IRadioVoice.hangupWaitingOrBackground() for the response returned.
+ */
+TEST_P(RadioVoiceTest, hangupWaitingOrBackground) {
+    LOG(DEBUG) << "hangupWaitingOrBackground";
+    serial = GetRandomSerialNumber();
+
+    radio_voice->hangupWaitingOrBackground(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
+                                     {RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+                                     CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "hangupWaitingOrBackground finished";
+}
+
+/*
+ * Test IRadioVoice.hangupForegroundResumeBackground() for the response returned.
+ */
+TEST_P(RadioVoiceTest, hangupForegroundResumeBackground) {
+    LOG(DEBUG) << "hangupForegroundResumeBackground";
+    serial = GetRandomSerialNumber();
+
+    radio_voice->hangupForegroundResumeBackground(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
+                                     {RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+                                     CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "hangupForegroundResumeBackground finished";
+}
+
+/*
+ * Test IRadioVoice.switchWaitingOrHoldingAndActive() for the response returned.
+ */
+TEST_P(RadioVoiceTest, switchWaitingOrHoldingAndActive) {
+    LOG(DEBUG) << "switchWaitingOrHoldingAndActive";
+    serial = GetRandomSerialNumber();
+
+    radio_voice->switchWaitingOrHoldingAndActive(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
+                                     {RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+                                     CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "switchWaitingOrHoldingAndActive finished";
+}
+
+/*
+ * Test IRadioVoice.conference() for the response returned.
+ */
+TEST_P(RadioVoiceTest, conference) {
+    LOG(DEBUG) << "conference";
+    serial = GetRandomSerialNumber();
+
+    radio_voice->conference(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
+                                     {RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+                                     CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "conference finished";
+}
+
+/*
+ * Test IRadioVoice.rejectCall() for the response returned.
+ */
+TEST_P(RadioVoiceTest, rejectCall) {
+    LOG(DEBUG) << "rejectCall";
+    serial = GetRandomSerialNumber();
+
+    radio_voice->rejectCall(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
+                                     {RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+                                     CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "rejectCall finished";
+}
+
+/*
+ * Test IRadioVoice.getLastCallFailCause() for the response returned.
+ */
+TEST_P(RadioVoiceTest, getLastCallFailCause) {
+    LOG(DEBUG) << "getLastCallFailCause";
+    serial = GetRandomSerialNumber();
+
+    radio_voice->getLastCallFailCause(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error, {RadioError::NONE},
+                                     CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "getLastCallFailCause finished";
+}
+
+/*
+ * Test IRadioVoice.getCallForwardStatus() for the response returned.
+ */
+TEST_P(RadioVoiceTest, getCallForwardStatus) {
+    LOG(DEBUG) << "getCallForwardStatus";
+    serial = GetRandomSerialNumber();
+    CallForwardInfo callInfo;
+    memset(&callInfo, 0, sizeof(callInfo));
+    callInfo.number = std::string();
+
+    radio_voice->getCallForwardStatus(serial, callInfo);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_voice->rspInfo.error,
+                {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+                CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "getCallForwardStatus finished";
+}
+
+/*
+ * Test IRadioVoice.setCallForward() for the response returned.
+ */
+TEST_P(RadioVoiceTest, setCallForward) {
+    LOG(DEBUG) << "setCallForward";
+    serial = GetRandomSerialNumber();
+    CallForwardInfo callInfo;
+    memset(&callInfo, 0, sizeof(callInfo));
+    callInfo.number = std::string();
+
+    radio_voice->setCallForward(serial, callInfo);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_voice->rspInfo.error,
+                {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+                CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "setCallForward finished";
+}
+
+/*
+ * Test IRadioVoice.getCallWaiting() for the response returned.
+ */
+TEST_P(RadioVoiceTest, getCallWaiting) {
+    LOG(DEBUG) << "getCallWaiting";
+    serial = GetRandomSerialNumber();
+
+    radio_voice->getCallWaiting(serial, 1);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_voice->rspInfo.error,
+                {RadioError::NONE, RadioError::INVALID_ARGUMENTS, RadioError::MODEM_ERR},
+                CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "getCallWaiting finished";
+}
+
+/*
+ * Test IRadioVoice.setCallWaiting() for the response returned.
+ */
+TEST_P(RadioVoiceTest, setCallWaiting) {
+    LOG(DEBUG) << "setCallWaiting";
+    serial = GetRandomSerialNumber();
+
+    radio_voice->setCallWaiting(serial, true, 1);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_voice->rspInfo.error,
+                {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+                CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "setCallWaiting finished";
+}
+
+/*
+ * Test IRadioVoice.acceptCall() for the response returned.
+ */
+TEST_P(RadioVoiceTest, acceptCall) {
+    LOG(DEBUG) << "acceptCall";
+    serial = GetRandomSerialNumber();
+
+    radio_voice->acceptCall(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
+                                     {RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+                                     CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "acceptCall finished";
+}
+
+/*
+ * Test IRadioVoice.separateConnection() for the response returned.
+ */
+TEST_P(RadioVoiceTest, separateConnection) {
+    LOG(DEBUG) << "separateConnection";
+    serial = GetRandomSerialNumber();
+
+    radio_voice->separateConnection(serial, 1);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_voice->rspInfo.error,
+                {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+                CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "separateConnection finished";
+}
+
+/*
+ * Test IRadioVoice.explicitCallTransfer() for the response returned.
+ */
+TEST_P(RadioVoiceTest, explicitCallTransfer) {
+    LOG(DEBUG) << "explicitCallTransfer";
+    serial = GetRandomSerialNumber();
+
+    radio_voice->explicitCallTransfer(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
+                                     {RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+                                     CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "explicitCallTransfer finished";
+}
+
+/*
+ * Test IRadioVoice.sendCdmaFeatureCode() for the response returned.
+ */
+TEST_P(RadioVoiceTest, sendCdmaFeatureCode) {
+    LOG(DEBUG) << "sendCdmaFeatureCode";
+    serial = GetRandomSerialNumber();
+
+    radio_voice->sendCdmaFeatureCode(serial, std::string());
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
+                                     {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
+                                      RadioError::INVALID_CALL_ID, RadioError::INVALID_MODEM_STATE,
+                                      RadioError::MODEM_ERR, RadioError::OPERATION_NOT_ALLOWED},
+                                     CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "sendCdmaFeatureCode finished";
+}
+
+/*
+ * Test IRadioVoice.sendDtmf() for the response returned.
+ */
+TEST_P(RadioVoiceTest, sendDtmf) {
+    LOG(DEBUG) << "sendDtmf";
+    serial = GetRandomSerialNumber();
+
+    radio_voice->sendDtmf(serial, "1");
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_voice->rspInfo.error,
+                {RadioError::NONE, RadioError::INVALID_ARGUMENTS, RadioError::INVALID_CALL_ID,
+                 RadioError::INVALID_MODEM_STATE, RadioError::MODEM_ERR},
+                CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "sendDtmf finished";
+}
+
+/*
+ * Test IRadioVoice.startDtmf() for the response returned.
+ */
+TEST_P(RadioVoiceTest, startDtmf) {
+    LOG(DEBUG) << "startDtmf";
+    serial = GetRandomSerialNumber();
+
+    radio_voice->startDtmf(serial, "1");
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_voice->rspInfo.error,
+                {RadioError::NONE, RadioError::INVALID_ARGUMENTS, RadioError::INVALID_CALL_ID,
+                 RadioError::INVALID_MODEM_STATE, RadioError::MODEM_ERR},
+                CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "startDtmf finished";
+}
+
+/*
+ * Test IRadioVoice.stopDtmf() for the response returned.
+ */
+TEST_P(RadioVoiceTest, stopDtmf) {
+    LOG(DEBUG) << "stopDtmf";
+    serial = GetRandomSerialNumber();
+
+    radio_voice->stopDtmf(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
+                                     {RadioError::NONE, RadioError::INVALID_CALL_ID,
+                                      RadioError::INVALID_MODEM_STATE, RadioError::MODEM_ERR},
+                                     CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "stopDtmf finished";
+}
+
+/*
+ * Test IRadioVoice.setMute() for the response returned.
+ */
+TEST_P(RadioVoiceTest, setMute) {
+    LOG(DEBUG) << "setMute";
+    serial = GetRandomSerialNumber();
+
+    radio_voice->setMute(serial, true);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
+                                     {RadioError::NONE, RadioError::INVALID_ARGUMENTS},
+                                     CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "setMute finished";
+}
+
+/*
+ * Test IRadioVoice.getMute() for the response returned.
+ */
+TEST_P(RadioVoiceTest, getMute) {
+    LOG(DEBUG) << "getMute";
+    serial = GetRandomSerialNumber();
+
+    radio_voice->getMute(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        EXPECT_EQ(RadioError::NONE, radioRsp_voice->rspInfo.error);
+    }
+    LOG(DEBUG) << "getMute finished";
+}
+
+/*
+ * Test IRadioVoice.sendBurstDtmf() for the response returned.
+ */
+TEST_P(RadioVoiceTest, sendBurstDtmf) {
+    LOG(DEBUG) << "sendBurstDtmf";
+    serial = GetRandomSerialNumber();
+
+    radio_voice->sendBurstDtmf(serial, "1", 0, 0);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
+                                     {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE,
+                                      RadioError::MODEM_ERR, RadioError::OPERATION_NOT_ALLOWED},
+                                     CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "sendBurstDtmf finished";
+}
+
+/*
+ * Test IRadioVoice.sendUssd() for the response returned.
+ */
+TEST_P(RadioVoiceTest, sendUssd) {
+    LOG(DEBUG) << "sendUssd";
+    serial = GetRandomSerialNumber();
+    radio_voice->sendUssd(serial, std::string("test"));
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_voice->rspInfo.error,
+                {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+                CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "sendUssd finished";
+}
+
+/*
+ * Test IRadioVoice.cancelPendingUssd() for the response returned.
+ */
+TEST_P(RadioVoiceTest, cancelPendingUssd) {
+    LOG(DEBUG) << "cancelPendingUssd";
+    serial = GetRandomSerialNumber();
+
+    radio_voice->cancelPendingUssd(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    if (cardStatus.cardState == CardStatus::STATE_ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+                radioRsp_voice->rspInfo.error,
+                {RadioError::NONE, RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+                CHECK_GENERAL_ERROR));
+    }
+    LOG(DEBUG) << "cancelPendingUssd finished";
+}
+
+/*
+ * Test IRadioVoice.isVoNrEnabled() for the response returned.
+ */
+TEST_P(RadioVoiceTest, isVoNrEnabled) {
+    LOG(DEBUG) << "isVoNrEnabled";
+    serial = GetRandomSerialNumber();
+
+    radio_voice->isVoNrEnabled(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
+                                 {RadioError::REQUEST_NOT_SUPPORTED, RadioError::NONE}));
+    LOG(DEBUG) << "isVoNrEnabled finished";
+}
+
+/*
+ * Test IRadioVoice.setVoNrEnabled() for the response returned.
+ */
+TEST_P(RadioVoiceTest, setVoNrEnabled) {
+    LOG(DEBUG) << "setVoNrEnabled";
+    serial = GetRandomSerialNumber();
+
+    radio_voice->setVoNrEnabled(serial, true);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
+                                 {RadioError::REQUEST_NOT_SUPPORTED, RadioError::NONE}));
+    LOG(DEBUG) << "setVoNrEnabled finished";
+}
diff --git a/radio/aidl/vts/radio_voice_utils.h b/radio/aidl/vts/radio_voice_utils.h
new file mode 100644
index 0000000..0c3df7f
--- /dev/null
+++ b/radio/aidl/vts/radio_voice_utils.h
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/radio/voice/BnRadioVoiceIndication.h>
+#include <aidl/android/hardware/radio/voice/BnRadioVoiceResponse.h>
+#include <aidl/android/hardware/radio/voice/IRadioVoice.h>
+
+#include "radio_aidl_hal_utils.h"
+#include "radio_network_utils.h"
+
+using namespace aidl::android::hardware::radio::voice;
+
+class RadioVoiceTest;
+
+/* Callback class for radio voice response */
+class RadioVoiceResponse : public BnRadioVoiceResponse {
+  protected:
+    RadioServiceTest& parent_voice;
+
+  public:
+    RadioVoiceResponse(RadioServiceTest& parent_voice);
+    virtual ~RadioVoiceResponse() = default;
+
+    RadioResponseInfo rspInfo;
+    std::vector<Call> currentCalls;
+
+    virtual ndk::ScopedAStatus acceptCallResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus acknowledgeRequest(int32_t serial) override;
+
+    virtual ndk::ScopedAStatus cancelPendingUssdResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus conferenceResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus dialResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus emergencyDialResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus exitEmergencyCallbackModeResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus explicitCallTransferResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus getCallForwardStatusResponse(
+            const RadioResponseInfo& info,
+            const std::vector<CallForwardInfo>& call_forwardInfos) override;
+
+    virtual ndk::ScopedAStatus getCallWaitingResponse(const RadioResponseInfo& info, bool enable,
+                                                      int32_t serviceClass) override;
+
+    virtual ndk::ScopedAStatus getClipResponse(const RadioResponseInfo& info,
+                                               ClipStatus status) override;
+
+    virtual ndk::ScopedAStatus getClirResponse(const RadioResponseInfo& info, int32_t n,
+                                               int32_t m) override;
+
+    virtual ndk::ScopedAStatus getCurrentCallsResponse(const RadioResponseInfo& info,
+                                                       const std::vector<Call>& calls) override;
+
+    virtual ndk::ScopedAStatus getLastCallFailCauseResponse(
+            const RadioResponseInfo& info, const LastCallFailCauseInfo& failCauseInfo) override;
+
+    virtual ndk::ScopedAStatus getMuteResponse(const RadioResponseInfo& info, bool enable) override;
+
+    virtual ndk::ScopedAStatus getPreferredVoicePrivacyResponse(const RadioResponseInfo& info,
+                                                                bool enable) override;
+
+    virtual ndk::ScopedAStatus getTtyModeResponse(const RadioResponseInfo& info,
+                                                  TtyMode mode) override;
+
+    virtual ndk::ScopedAStatus handleStkCallSetupRequestFromSimResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus hangupConnectionResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus hangupForegroundResumeBackgroundResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus hangupWaitingOrBackgroundResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus isVoNrEnabledResponse(const RadioResponseInfo& info,
+                                                     bool enable) override;
+
+    virtual ndk::ScopedAStatus rejectCallResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus sendBurstDtmfResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus sendCdmaFeatureCodeResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus sendDtmfResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus sendUssdResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus separateConnectionResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setCallForwardResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setCallWaitingResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setClirResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setMuteResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setPreferredVoicePrivacyResponse(
+            const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setTtyModeResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus setVoNrEnabledResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus startDtmfResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus stopDtmfResponse(const RadioResponseInfo& info) override;
+
+    virtual ndk::ScopedAStatus switchWaitingOrHoldingAndActiveResponse(
+            const RadioResponseInfo& info) override;
+};
+
+/* Callback class for radio voice indication */
+class RadioVoiceIndication : public BnRadioVoiceIndication {
+  protected:
+    RadioServiceTest& parent_voice;
+
+  public:
+    RadioVoiceIndication(RadioServiceTest& parent_voice);
+    virtual ~RadioVoiceIndication() = default;
+
+    virtual ndk::ScopedAStatus callRing(RadioIndicationType type, bool isGsm,
+                                        const CdmaSignalInfoRecord& record) override;
+
+    virtual ndk::ScopedAStatus callStateChanged(RadioIndicationType type) override;
+
+    virtual ndk::ScopedAStatus cdmaCallWaiting(RadioIndicationType type,
+                                               const CdmaCallWaiting& callWaitingRecord) override;
+
+    virtual ndk::ScopedAStatus cdmaInfoRec(
+            RadioIndicationType type, const std::vector<CdmaInformationRecord>& records) override;
+
+    virtual ndk::ScopedAStatus cdmaOtaProvisionStatus(RadioIndicationType type,
+                                                      CdmaOtaProvisionStatus status) override;
+
+    virtual ndk::ScopedAStatus currentEmergencyNumberList(
+            RadioIndicationType type,
+            const std::vector<EmergencyNumber>& emergencyNumberList) override;
+
+    virtual ndk::ScopedAStatus enterEmergencyCallbackMode(RadioIndicationType type) override;
+
+    virtual ndk::ScopedAStatus exitEmergencyCallbackMode(RadioIndicationType type) override;
+
+    virtual ndk::ScopedAStatus indicateRingbackTone(RadioIndicationType type, bool start) override;
+
+    virtual ndk::ScopedAStatus onSupplementaryServiceIndication(
+            RadioIndicationType type, const StkCcUnsolSsResult& ss) override;
+
+    virtual ndk::ScopedAStatus onUssd(RadioIndicationType type, UssdModeType modeType,
+                                      const std::string& msg) override;
+
+    virtual ndk::ScopedAStatus resendIncallMute(RadioIndicationType type) override;
+
+    virtual ndk::ScopedAStatus srvccStateNotify(RadioIndicationType type,
+                                                SrvccState state) override;
+
+    virtual ndk::ScopedAStatus stkCallControlAlphaNotify(RadioIndicationType type,
+                                                         const std::string& alpha) override;
+
+    virtual ndk::ScopedAStatus stkCallSetup(RadioIndicationType type, int64_t timeout) override;
+};
+
+// The main test class for Radio AIDL Voice.
+class RadioVoiceTest : public ::testing::TestWithParam<std::string>, public RadioServiceTest {
+  protected:
+    /* Clear Potential Established Calls */
+    virtual ndk::ScopedAStatus clearPotentialEstablishedCalls();
+    std::shared_ptr<network::IRadioNetwork> radio_network;
+    std::shared_ptr<RadioNetworkResponse> radioRsp_network;
+    std::shared_ptr<RadioNetworkIndication> radioInd_network;
+
+  public:
+    virtual void SetUp() override;
+
+    /* radio voice service handle */
+    std::shared_ptr<IRadioVoice> radio_voice;
+    /* radio voice response handle */
+    std::shared_ptr<RadioVoiceResponse> radioRsp_voice;
+    /* radio voice indication handle */
+    std::shared_ptr<RadioVoiceIndication> radioInd_voice;
+};
diff --git a/radio/config/1.0/vts/functional/OWNERS b/radio/config/1.0/vts/functional/OWNERS
new file mode 100644
index 0000000..badd6d7
--- /dev/null
+++ b/radio/config/1.0/vts/functional/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 20868
+jminjie@google.com
+sarahchin@google.com
+amitmahajan@google.com
+shuoq@google.com
+jackyu@google.com
diff --git a/radio/config/1.1/vts/OWNERS b/radio/config/1.1/vts/OWNERS
new file mode 100644
index 0000000..4109967
--- /dev/null
+++ b/radio/config/1.1/vts/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 20868
+include /radio/1.0/vts/OWNERS
diff --git a/radio/config/1.2/vts/OWNERS b/radio/config/1.2/vts/OWNERS
new file mode 100644
index 0000000..4109967
--- /dev/null
+++ b/radio/config/1.2/vts/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 20868
+include /radio/1.0/vts/OWNERS
diff --git a/rebootescrow/aidl/default/Android.bp b/rebootescrow/aidl/default/Android.bp
index 1f67a3e..4409314 100644
--- a/rebootescrow/aidl/default/Android.bp
+++ b/rebootescrow/aidl/default/Android.bp
@@ -29,7 +29,7 @@
     shared_libs: [
         "libbase",
         "libbinder_ndk",
-        "android.hardware.rebootescrow-V1-ndk_platform",
+        "android.hardware.rebootescrow-V1-ndk",
     ],
     export_include_dirs: ["include"],
     srcs: [
@@ -56,7 +56,7 @@
     shared_libs: [
         "libbase",
         "libbinder_ndk",
-        "android.hardware.rebootescrow-V1-ndk_platform",
+        "android.hardware.rebootescrow-V1-ndk",
     ],
     static_libs: [
         "libhadamardutils",
diff --git a/rebootescrow/aidl/default/service.cpp b/rebootescrow/aidl/default/service.cpp
index 8a8086b..dc06c71 100644
--- a/rebootescrow/aidl/default/service.cpp
+++ b/rebootescrow/aidl/default/service.cpp
@@ -34,7 +34,7 @@
     auto re = ndk::SharedRefBase::make<RebootEscrow>(rebootEscrowDevicePath);
     const std::string instance = std::string() + RebootEscrow::descriptor + "/default";
     binder_status_t status = AServiceManager_addService(re->asBinder().get(), instance.c_str());
-    CHECK(status == STATUS_OK);
+    CHECK_EQ(status, STATUS_OK);
 
     ABinderProcess_joinThreadPool();
     return EXIT_FAILURE;
diff --git a/renderscript/1.0/vts/functional/OWNERS b/renderscript/1.0/vts/functional/OWNERS
new file mode 100644
index 0000000..d785790
--- /dev/null
+++ b/renderscript/1.0/vts/functional/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 43047
+butlermichael@google.com
+dgross@google.com
+jeanluc@google.com
+miaowang@google.com
+xusongw@google.com
diff --git a/secure_element/1.0/vts/functional/OWNERS b/secure_element/1.0/vts/functional/OWNERS
new file mode 100644
index 0000000..a7ee7e9
--- /dev/null
+++ b/secure_element/1.0/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 456592
+jackcwyu@google.com
diff --git a/secure_element/1.1/vts/functional/OWNERS b/secure_element/1.1/vts/functional/OWNERS
new file mode 100644
index 0000000..a7ee7e9
--- /dev/null
+++ b/secure_element/1.1/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 456592
+jackcwyu@google.com
diff --git a/secure_element/1.2/vts/functional/OWNERS b/secure_element/1.2/vts/functional/OWNERS
new file mode 100644
index 0000000..a7ee7e9
--- /dev/null
+++ b/secure_element/1.2/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 456592
+jackcwyu@google.com
diff --git a/security/OWNERS b/security/OWNERS
new file mode 100644
index 0000000..54d820a
--- /dev/null
+++ b/security/OWNERS
@@ -0,0 +1,5 @@
+drysdale@google.com
+jbires@google.com
+jdanis@google.com
+seleneh@google.com
+swillden@google.com
diff --git a/security/dice/aidl/Android.bp b/security/dice/aidl/Android.bp
new file mode 100644
index 0000000..8c31e26
--- /dev/null
+++ b/security/dice/aidl/Android.bp
@@ -0,0 +1,55 @@
+// Copyright 2021, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+aidl_interface {
+    name: "android.hardware.security.dice",
+    vendor_available: true,
+    srcs: [
+        "android/hardware/security/dice/*.aidl",
+    ],
+    stability: "vintf",
+    backend: {
+        java: {
+            enabled: false,
+            platform_apis: false,
+        },
+        ndk: {
+            vndk: {
+                enabled: true,
+            },
+            apps_enabled: false,
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.compos",
+            ],
+        },
+        rust: {
+            enabled: true,
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.compos",
+            ],
+        },
+    },
+    //     versions: ["1"],
+}
diff --git a/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/Bcc.aidl b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/Bcc.aidl
new file mode 100644
index 0000000..5af7358
--- /dev/null
+++ b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/Bcc.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.security.dice;
+/* @hide */
+@RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability
+parcelable Bcc {
+  byte[] data;
+}
diff --git a/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/BccHandover.aidl b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/BccHandover.aidl
new file mode 100644
index 0000000..8baca94
--- /dev/null
+++ b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/BccHandover.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.security.dice;
+/* @hide */
+@RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability
+parcelable BccHandover {
+  byte[32] cdiAttest;
+  byte[32] cdiSeal;
+  android.hardware.security.dice.Bcc bcc;
+}
diff --git a/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/Config.aidl b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/Config.aidl
new file mode 100644
index 0000000..78dd2f8
--- /dev/null
+++ b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/Config.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.security.dice;
+/* @hide */
+@RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability
+parcelable Config {
+  byte[] desc;
+}
diff --git a/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/IDiceDevice.aidl b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/IDiceDevice.aidl
new file mode 100644
index 0000000..383f4d1
--- /dev/null
+++ b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/IDiceDevice.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.security.dice;
+/* @hide */
+@SensitiveData @VintfStability
+interface IDiceDevice {
+  android.hardware.security.dice.Signature sign(in android.hardware.security.dice.InputValues[] id, in byte[] payload);
+  android.hardware.security.dice.Bcc getAttestationChain(in android.hardware.security.dice.InputValues[] inputValues);
+  android.hardware.security.dice.BccHandover derive(in android.hardware.security.dice.InputValues[] inputValues);
+  void demote(in android.hardware.security.dice.InputValues[] inputValues);
+}
diff --git a/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/InputValues.aidl b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/InputValues.aidl
new file mode 100644
index 0000000..e43c429
--- /dev/null
+++ b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/InputValues.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.security.dice;
+/* @hide */
+@RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability
+parcelable InputValues {
+  byte[64] codeHash;
+  android.hardware.security.dice.Config config;
+  byte[64] authorityHash;
+  @nullable byte[] authorityDescriptor;
+  android.hardware.security.dice.Mode mode = android.hardware.security.dice.Mode.NOT_INITIALIZED;
+  byte[64] hidden;
+}
diff --git a/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/Mode.aidl b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/Mode.aidl
new file mode 100644
index 0000000..295c32e
--- /dev/null
+++ b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/Mode.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.security.dice;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum Mode {
+  NOT_INITIALIZED = 0,
+  NORMAL = 1,
+  DEBUG = 2,
+  RECOVERY = 3,
+}
diff --git a/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/ResponseCode.aidl b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/ResponseCode.aidl
new file mode 100644
index 0000000..c13afa6
--- /dev/null
+++ b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/ResponseCode.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.security.dice;
+@Backing(type="int") @VintfStability
+enum ResponseCode {
+  PERMISSION_DENIED = 1,
+  SYSTEM_ERROR = 2,
+  NOT_IMPLEMENTED = 3,
+  DEMOTION_FAILED = 4,
+}
diff --git a/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/Signature.aidl b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/Signature.aidl
new file mode 100644
index 0000000..294170d
--- /dev/null
+++ b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/Signature.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.security.dice;
+/* @hide */
+@RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability
+parcelable Signature {
+  byte[] data;
+}
diff --git a/security/dice/aidl/android/hardware/security/dice/Bcc.aidl b/security/dice/aidl/android/hardware/security/dice/Bcc.aidl
new file mode 100644
index 0000000..983915e
--- /dev/null
+++ b/security/dice/aidl/android/hardware/security/dice/Bcc.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.security.dice;
+
+/**
+ * A DICE certificate chain following the Boot Certificate Chain (BCC) specification.
+ * @hide
+ */
+@VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
+parcelable Bcc {
+    /**
+     * The DICE certificate chain CBOR encoded following the BCC specification. The CDDL
+     * specification for BCC can be found here [1].
+     *
+     * @see <a
+     *         href="https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl">
+     *    BCC CDDL specification
+     * </a>
+     */
+    byte[] data;
+}
diff --git a/security/dice/aidl/android/hardware/security/dice/BccHandover.aidl b/security/dice/aidl/android/hardware/security/dice/BccHandover.aidl
new file mode 100644
index 0000000..6ca862c
--- /dev/null
+++ b/security/dice/aidl/android/hardware/security/dice/BccHandover.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.security.dice;
+
+import android.hardware.security.dice.Bcc;
+
+/**
+ * Represents one set of DICE artifacts.
+ *
+ * @hide
+ */
+@VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
+parcelable BccHandover {
+    /**
+     * CDI_attest. Must be exactly 32 bytes of data.
+     */
+    byte[32] cdiAttest;
+    /**
+     * CDI_seal. Must be exactly 32 bytes of data.
+     */
+    byte[32] cdiSeal;
+    /**
+     * CBOR encoded BCC.
+     *
+     * @see <a
+     *         href="https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl">
+     *    BCC CDDL specification
+     * </a>
+     */
+    Bcc bcc;
+}
diff --git a/security/dice/aidl/android/hardware/security/dice/Config.aidl b/security/dice/aidl/android/hardware/security/dice/Config.aidl
new file mode 100644
index 0000000..6decfc5
--- /dev/null
+++ b/security/dice/aidl/android/hardware/security/dice/Config.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.security.dice;
+
+/**
+ * DICE config descriptor as described in at
+ * <a
+ * href="https://pigweed.googlesource.com/open-dice/+/refs/heads/main/docs/specification.md#input-values">
+ *     input-values
+ * </a>
+ * @hide
+ */
+@VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
+parcelable Config {
+    /**
+     * A free form descriptor. This should follow the BCC Configuration Descriptor.
+     * @see <a
+     *         href="https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl">
+     *     BccPayload field -4670548
+     * </a>
+     */
+    byte[] desc;
+}
diff --git a/security/dice/aidl/android/hardware/security/dice/IDiceDevice.aidl b/security/dice/aidl/android/hardware/security/dice/IDiceDevice.aidl
new file mode 100644
index 0000000..709aede
--- /dev/null
+++ b/security/dice/aidl/android/hardware/security/dice/IDiceDevice.aidl
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.security.dice;
+
+import android.hardware.security.dice.Bcc;
+import android.hardware.security.dice.BccHandover;
+import android.hardware.security.dice.InputValues;
+import android.hardware.security.dice.Signature;
+
+/**
+ * IDiceDevice specifies an interface that allows access to the Android instance's DICE artifacts.
+ *
+ * <h2>Features</h2>
+ *
+ * The dice device provides access to the component's CDI_SEAL and CDI_ATTEST secrets as well
+ * as to its attestation certificate chain. The "component" is the Android instance running this
+ * HAL service and the secrets and attestation chain must include all boot stage components,
+ * the kernel, and the verified boot information (VBA).
+ *
+ * Implementations provide the following operations:
+ * <li> sign - Signing a payload with a key derived from CDI_ATTEST.
+ * <li> getAttestationChain - Retrieve the component's attestation certificate chain.
+ * <li> derive - Retrieve the component's DICE artifacts.
+ *
+ * @see <a
+ *         href="https://pigweed.googlesource.com/open-dice/+/refs/heads/main/docs/specification.md">
+ *     Open-dice Specification
+ * </a>
+ * @see <a
+ *         href="https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl">
+ *     Boot Certificate Chain (BCC) CDDL specification
+ * </a>
+ * @hide
+ */
+@SensitiveData
+@VintfStability
+interface IDiceDevice {
+    /**
+     * Uses the a key derived from the component's, or a child's given by <code>inputValues</code>,
+     * attestation secret to sign the payload using RFC 8032 Pure Ed25519 and returns the
+     * signature. The payload is limited to 1024 bytes.
+     *
+     * @see <a href="https://datatracker.ietf.org/doc/html/rfc8032">RFC 8032</a>
+     */
+    Signature sign(in InputValues[] id, in byte[] payload);
+
+    /**
+     * Returns the attestation chain of the component if <code>inputValues</code> is empty or the
+     * chain to the given child of the component identified by the <code>inputValues</code> vector.
+     *
+     * ## Error as service specific exception:
+     *     ResponseCode::PERMISSION_DENIED if the caller is not sufficiently privileged.
+     */
+    Bcc getAttestationChain(in InputValues[] inputValues);
+
+    /**
+     * This function allows a client to become a resident node. A resident node is a node that
+     * manages its own dice secrets as opposed to using them by proxy, i.e., by calling sign
+     * and getAttestationChain. Called with empty <code>inputValues</code> vectors, an
+     * implementation returns the component's DICE secrets. If the <code>inputValues</code> vector
+     * is given the appropriate derivations are performed starting from the component's level.
+     *
+     * ## Error as service specific exception:
+     *     ResponseCode::PERMISSION_DENIED if the implementation does not allow resident nodes
+     *     at the client's level.
+     */
+    BccHandover derive(in InputValues[] inputValues);
+
+    /**
+     * This demotes the implementation of this interface.
+     * When called, the implementation performs appropriate derivation steps using
+     * <code>inputValues</code>, traversing the vector in ascending order. Then it replaces its
+     * stored DICE artifacts with the newly derived ones.
+     *
+     * IMPORTANT: When the function returns, all remnants of the previous DICE artifacts must
+     * have been purged from memory.
+     *
+     * This operation is not reversible until the next reboot. Further demotion is always
+     * possible.
+     *
+     * ## Error as service specific exception:
+     *     ResponseCode::DEMOTION_FAILED if the implementation failed to demote itself
+     *     or was unable to purge previous DICE artifacts from memory.
+     */
+    void demote(in InputValues[] inputValues);
+}
diff --git a/security/dice/aidl/android/hardware/security/dice/InputValues.aidl b/security/dice/aidl/android/hardware/security/dice/InputValues.aidl
new file mode 100644
index 0000000..711d523
--- /dev/null
+++ b/security/dice/aidl/android/hardware/security/dice/InputValues.aidl
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.security.dice;
+
+import android.hardware.security.dice.Config;
+import android.hardware.security.dice.Mode;
+
+/**
+ * DICE input values for certificate and CDI generation.
+ *
+ * @see <a
+ *         href="https://pigweed.googlesource.com/open-dice/+/refs/heads/main/docs/specification.md#input-values">
+ *     Open-dice input-values
+ * </a>
+ * @hide
+ */
+@RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
+@VintfStability
+parcelable InputValues {
+    /**
+     * The target code hash. Must be exactly 64 bytes.
+     */
+    byte[64] codeHash;
+    /**
+     * The configuration data.
+     */
+    Config config;
+    /**
+     * The authority hash. Must be exactly 64 bytes. Must be all zero if unused.
+     */
+    byte[64] authorityHash;
+    /**
+     * Optional free form authorityDescriptor.
+     */
+    @nullable byte[] authorityDescriptor;
+    /**
+     * The mode of operation. Normal, Debug, Maintenance, or not initialized.
+     */
+    Mode mode = Mode.NOT_INITIALIZED;
+    /**
+     * Optional hidden values. Must be exactly 64 bytes. Must be all zero if unused.
+     */
+    byte[64] hidden;
+}
diff --git a/security/dice/aidl/android/hardware/security/dice/Mode.aidl b/security/dice/aidl/android/hardware/security/dice/Mode.aidl
new file mode 100644
index 0000000..3b3bfdc
--- /dev/null
+++ b/security/dice/aidl/android/hardware/security/dice/Mode.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.security.dice;
+
+/**
+ * DICE mode values as defined at
+ *
+ * @see <a
+ *         href="https://pigweed.googlesource.com/open-dice/+/refs/heads/main/docs/specification.md#mode-value-details">
+ *     open-dice mode-value-details
+ * </a>
+ * @hide
+ */
+@Backing(type="int")
+@VintfStability
+enum Mode {
+    NOT_INITIALIZED = 0,
+    NORMAL = 1,
+    DEBUG = 2,
+    /**
+     * The recovery mode is also referred to as "maintenance" mode.
+     */
+    RECOVERY = 3,
+}
diff --git a/security/dice/aidl/android/hardware/security/dice/ResponseCode.aidl b/security/dice/aidl/android/hardware/security/dice/ResponseCode.aidl
new file mode 100644
index 0000000..3e77cf7
--- /dev/null
+++ b/security/dice/aidl/android/hardware/security/dice/ResponseCode.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.security.dice;
+
+@Backing(type="int")
+/**
+ * These response codes are used as service specific exception codes by
+ * IDiceDevice.
+ * @hide
+ */
+@VintfStability
+enum ResponseCode {
+    /**
+     * The caller has insufficient privilege to access the DICE API.
+     */
+    PERMISSION_DENIED = 1,
+    /**
+     * An unexpected error occurred, likely with IO or IPC.
+     */
+    SYSTEM_ERROR = 2,
+    /**
+     * Returned if the called function is not implemented.
+     */
+    NOT_IMPLEMENTED = 3,
+    /**
+     * An attempt to demote the implementation failed.
+     */
+    DEMOTION_FAILED = 4,
+}
diff --git a/security/dice/aidl/android/hardware/security/dice/Signature.aidl b/security/dice/aidl/android/hardware/security/dice/Signature.aidl
new file mode 100644
index 0000000..ea3594f
--- /dev/null
+++ b/security/dice/aidl/android/hardware/security/dice/Signature.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.security.dice;
+
+/**
+ * This parcelable represents a Signature. It is used as return value of IDiceNode::sign.
+ *
+ * @hide
+ */
+@RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
+@VintfStability
+parcelable Signature {
+    /**
+     * The RFC 8032 PureEd25519 signature.
+     * @see <a href="https://datatracker.ietf.org/doc/html/rfc8032">RFC 8032</a>
+     */
+    byte[] data;
+}
diff --git a/security/dice/aidl/default/Android.bp b/security/dice/aidl/default/Android.bp
new file mode 100644
index 0000000..b67a44a
--- /dev/null
+++ b/security/dice/aidl/default/Android.bp
@@ -0,0 +1,30 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+rust_binary {
+    name: "android.hardware.security.dice-service.non-secure-software",
+    srcs: ["service.rs"],
+    relative_install_path: "hw",
+    vendor: true,
+    rustlibs: [
+        "android.hardware.security.dice-V1-rust",
+        "libdiced_open_dice_cbor",
+        "libdiced_sample_inputs",
+        "libdiced_vendor",
+        "libandroid_logger",
+        "libanyhow",
+        "libbinder_rs",
+        "liblog_rust",
+        "libserde",
+    ],
+    init_rc: ["android.hardware.security.dice-service.non-secure-software.rc"],
+    vintf_fragments: [
+        "android.hardware.security.dice-service.non-secure-software.xml",
+    ],
+}
diff --git a/security/dice/aidl/default/android.hardware.security.dice-service.non-secure-software.rc b/security/dice/aidl/default/android.hardware.security.dice-service.non-secure-software.rc
new file mode 100644
index 0000000..28e43c3
--- /dev/null
+++ b/security/dice/aidl/default/android.hardware.security.dice-service.non-secure-software.rc
@@ -0,0 +1,9 @@
+service vendor.dice /vendor/bin/hw/android.hardware.security.dice-service.non-secure-software
+    class early_hal
+    user nobody
+    # The diced HAL cannot be allowed to restart. When it crashes for any reason.
+    # it loses security critical state. The only remedy is to restart the device.
+    # This may be implementation depended. It is safe to restart the HAL if the
+    # state change during a call to "demote" is is preserved.
+    # see android/hardware/security/dice/IDiceDevice.aidl for details on "demote".
+    oneshot
diff --git a/security/dice/aidl/default/android.hardware.security.dice-service.non-secure-software.xml b/security/dice/aidl/default/android.hardware.security.dice-service.non-secure-software.xml
new file mode 100644
index 0000000..94ef243
--- /dev/null
+++ b/security/dice/aidl/default/android.hardware.security.dice-service.non-secure-software.xml
@@ -0,0 +1,6 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.security.dice</name>
+        <fqname>IDiceDevice/default</fqname>
+    </hal>
+</manifest>
\ No newline at end of file
diff --git a/security/dice/aidl/default/service.rs b/security/dice/aidl/default/service.rs
new file mode 100644
index 0000000..eebf333
--- /dev/null
+++ b/security/dice/aidl/default/service.rs
@@ -0,0 +1,107 @@
+// Copyright 2021, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Main entry point for the android.hardware.security.dice service.
+
+use anyhow::Result;
+use diced::{
+    dice,
+    hal_node::{DiceArtifacts, DiceDevice, ResidentHal, UpdatableDiceArtifacts},
+};
+use diced_sample_inputs::make_sample_bcc_and_cdis;
+use serde::{Deserialize, Serialize};
+use std::convert::TryInto;
+use std::panic;
+use std::sync::Arc;
+
+static DICE_HAL_SERVICE_NAME: &str = "android.hardware.security.dice.IDiceDevice/default";
+
+#[derive(Debug, Serialize, Deserialize, Clone)]
+struct InsecureSerializableArtifacts {
+    cdi_attest: [u8; dice::CDI_SIZE],
+    cdi_seal: [u8; dice::CDI_SIZE],
+    bcc: Vec<u8>,
+}
+
+impl DiceArtifacts for InsecureSerializableArtifacts {
+    fn cdi_attest(&self) -> &[u8; dice::CDI_SIZE] {
+        &self.cdi_attest
+    }
+    fn cdi_seal(&self) -> &[u8; dice::CDI_SIZE] {
+        &self.cdi_seal
+    }
+    fn bcc(&self) -> Vec<u8> {
+        self.bcc.clone()
+    }
+}
+
+impl UpdatableDiceArtifacts for InsecureSerializableArtifacts {
+    fn with_artifacts<F, T>(&self, f: F) -> Result<T>
+    where
+        F: FnOnce(&dyn DiceArtifacts) -> Result<T>,
+    {
+        f(self)
+    }
+    fn update(self, new_artifacts: &impl DiceArtifacts) -> Result<Self> {
+        Ok(Self {
+            cdi_attest: *new_artifacts.cdi_attest(),
+            cdi_seal: *new_artifacts.cdi_seal(),
+            bcc: new_artifacts.bcc(),
+        })
+    }
+}
+
+fn main() {
+    android_logger::init_once(
+        android_logger::Config::default()
+            .with_tag("android.hardware.security.dice")
+            .with_min_level(log::Level::Debug),
+    );
+    // Redirect panic messages to logcat.
+    panic::set_hook(Box::new(|panic_info| {
+        log::error!("{}", panic_info);
+    }));
+
+    // Saying hi.
+    log::info!("android.hardware.security.dice is starting.");
+
+    let (cdi_attest, cdi_seal, bcc) =
+        make_sample_bcc_and_cdis().expect("Failed to construct sample dice chain.");
+
+    let hal_impl = Arc::new(
+        unsafe {
+            // Safety: ResidentHal cannot be used in multi threaded processes.
+            // This service does not start a thread pool. The main thread is the only thread
+            // joining the thread pool, thereby keeping the process single threaded.
+            ResidentHal::new(InsecureSerializableArtifacts {
+                cdi_attest: cdi_attest[..]
+                    .try_into()
+                    .expect("Failed to convert cdi_attest to array reference."),
+                cdi_seal: cdi_seal[..]
+                    .try_into()
+                    .expect("Failed to convert cdi_seal to array reference."),
+                bcc,
+            })
+        }
+        .expect("Failed to create ResidentHal implementation."),
+    );
+
+    let hal = DiceDevice::new_as_binder(hal_impl).expect("Failed to construct hal service.");
+
+    binder::add_service(DICE_HAL_SERVICE_NAME, hal.as_binder())
+        .expect("Failed to register IDiceDevice Service");
+
+    log::info!("Joining thread pool now.");
+    binder::ProcessState::join_thread_pool();
+}
diff --git a/security/dice/aidl/vts/functional/Android.bp b/security/dice/aidl/vts/functional/Android.bp
new file mode 100644
index 0000000..f5bc949
--- /dev/null
+++ b/security/dice/aidl/vts/functional/Android.bp
@@ -0,0 +1,54 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+rust_test {
+    name: "VtsAidlDiceTargetTest",
+    srcs: [
+        "dice_test.rs",
+    ],
+    require_root: true,
+    auto_gen_config: true,
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+
+    rustlibs: [
+        "android.hardware.security.dice-V1-rust",
+        "libanyhow",
+        "libbinder_rs",
+        "libdiced_open_dice_cbor",
+        "libdiced_sample_inputs",
+        "libdiced_utils",
+        "libkeystore2_vintf_rust",
+    ],
+}
+
+rust_test {
+    name: "VtsAidlDiceDemoteTargetTest",
+    srcs: [
+        "dice_demote_test.rs",
+    ],
+
+    test_config: "VtsAidlDiceDemoteTargetTest.xml",
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+
+    rustlibs: [
+        "android.hardware.security.dice-V1-rust",
+        "libanyhow",
+        "libbinder_rs",
+        "libdiced_open_dice_cbor",
+        "libdiced_sample_inputs",
+        "libdiced_utils",
+        "libkeystore2_vintf_rust",
+    ],
+}
diff --git a/security/dice/aidl/vts/functional/VtsAidlDiceDemoteTargetTest.xml b/security/dice/aidl/vts/functional/VtsAidlDiceDemoteTargetTest.xml
new file mode 100644
index 0000000..2991580
--- /dev/null
+++ b/security/dice/aidl/vts/functional/VtsAidlDiceDemoteTargetTest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<configuration description="Config to run VtsAidlDiceDemoteTargetTest device tests.">
+
+    <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="VtsAidlDiceDemoteTargetTest->/data/local/tmp/VtsAidlDiceDemoteTargetTest" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.rust.RustBinaryTest" >
+        <option name="test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="VtsAidlDiceDemoteTargetTest" />
+    </test>
+    <target_preparer class="com.android.tradefed.targetprep.RebootTargetPreparer" />
+
+</configuration>
\ No newline at end of file
diff --git a/security/dice/aidl/vts/functional/dice_demote_test.rs b/security/dice/aidl/vts/functional/dice_demote_test.rs
new file mode 100644
index 0000000..02ff2a4
--- /dev/null
+++ b/security/dice/aidl/vts/functional/dice_demote_test.rs
@@ -0,0 +1,67 @@
+// Copyright 2021, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use diced_open_dice_cbor as dice;
+use diced_sample_inputs;
+use diced_utils;
+use std::convert::TryInto;
+
+mod utils;
+use utils::with_connection;
+
+// This test calls derive with an empty argument vector, then demotes the HAL using
+// a set of three input values, and then calls derive with empty argument vector again.
+// It then performs the same three derivation steps on the result of the former and compares
+// the result to the result of the latter.
+#[test]
+fn demote_test() {
+    with_connection(|device| {
+        let input_values = diced_sample_inputs::get_input_values_vector();
+        let former = device.derive(&[]).expect("Trying to call derive.");
+        device
+            .demote(&input_values)
+            .expect("Trying to call demote with input values.");
+
+        let latter = device
+            .derive(&[])
+            .expect("Trying to call derive after demote.");
+
+        let artifacts = diced_utils::ResidentArtifacts::new(
+            former.cdiAttest[..].try_into().unwrap(),
+            former.cdiSeal[..].try_into().unwrap(),
+            &former.bcc.data,
+        )
+        .unwrap();
+
+        let input_values: Vec<diced_utils::InputValues> = input_values
+            .iter()
+            .map(|v| v.into())
+            .collect();
+
+        let artifacts = artifacts
+            .execute_steps(input_values.iter().map(|v| v as &dyn dice::InputValues))
+            .unwrap();
+        let (cdi_attest, cdi_seal, bcc) = artifacts.into_tuple();
+        let from_former = diced_utils::make_bcc_handover(
+            cdi_attest[..].try_into().unwrap(),
+            cdi_seal[..].try_into().unwrap(),
+            &bcc,
+        )
+        .unwrap();
+        // TODO b/204938506 when we have a parser/verifier, check equivalence rather
+        // than bit by bit equality.
+        assert_eq!(latter, from_former);
+        Ok(())
+    })
+}
diff --git a/security/dice/aidl/vts/functional/dice_test.rs b/security/dice/aidl/vts/functional/dice_test.rs
new file mode 100644
index 0000000..574b634
--- /dev/null
+++ b/security/dice/aidl/vts/functional/dice_test.rs
@@ -0,0 +1,82 @@
+// Copyright 2021, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use diced_open_dice_cbor as dice;
+use diced_sample_inputs;
+use diced_utils;
+use std::convert::{TryInto, Into};
+
+mod utils;
+use utils::with_connection;
+
+static TEST_MESSAGE: &[u8] = &[
+    // "My test message!"
+    0x4d, 0x79, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x21,
+    0x0a,
+];
+
+// This test calls derive with an empty argument vector and with a set of three input values.
+// It then performs the same three derivation steps on the result of the former and compares
+// the result to the result of the latter.
+#[test]
+fn equivalence_test() {
+    with_connection(|device| {
+        let input_values = diced_sample_inputs::get_input_values_vector();
+        let former = device.derive(&[]).expect("Trying to call derive.");
+        let latter = device
+            .derive(&input_values)
+            .expect("Trying to call derive with input values.");
+        let artifacts = diced_utils::ResidentArtifacts::new(
+            former.cdiAttest[..].try_into().unwrap(),
+            former.cdiSeal[..].try_into().unwrap(),
+            &former.bcc.data,
+        )
+        .unwrap();
+
+        let input_values: Vec<diced_utils::InputValues> = input_values
+            .iter()
+            .map(|v| v.into())
+            .collect();
+
+        let artifacts = artifacts
+            .execute_steps(input_values.iter().map(|v| v as &dyn dice::InputValues))
+            .unwrap();
+        let (cdi_attest, cdi_seal, bcc) = artifacts.into_tuple();
+        let from_former = diced_utils::make_bcc_handover(
+            cdi_attest[..].try_into().unwrap(),
+            cdi_seal[..].try_into().unwrap(),
+            &bcc,
+        )
+        .unwrap();
+        // TODO b/204938506 when we have a parser/verifier, check equivalence rather
+        // than bit by bit equality.
+        assert_eq!(latter, from_former);
+        Ok(())
+    })
+}
+
+#[test]
+fn sign_and_verify() {
+    with_connection(|device| {
+        let _signature = device
+            .sign(&[], TEST_MESSAGE)
+            .expect("Trying to call sign.");
+
+        let _bcc = device
+            .getAttestationChain(&[])
+            .expect("Trying to call getAttestationChain.");
+        // TODO b/204938506 check the signature with the bcc when the verifier is available.
+        Ok(())
+    })
+}
diff --git a/security/dice/aidl/vts/functional/utils.rs b/security/dice/aidl/vts/functional/utils.rs
new file mode 100644
index 0000000..4e6708e
--- /dev/null
+++ b/security/dice/aidl/vts/functional/utils.rs
@@ -0,0 +1,53 @@
+// Copyright 2021, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use android_hardware_security_dice::aidl::android::hardware::security::dice::IDiceDevice::IDiceDevice;
+use anyhow::Result;
+use binder::Strong;
+use keystore2_vintf::get_aidl_instances;
+use std::sync::Arc;
+
+static DICE_DEVICE_SERVICE_NAME: &str = &"android.hardware.security.dice";
+static DICE_DEVICE_INTERFACE_NAME: &str = &"IDiceDevice";
+
+/// This function iterates through all announced IDiceDevice services and runs the given test
+/// closure against connections to each of them. It also modifies the panic hook to indicate
+/// on which instance the test failed in case the test closure panics.
+pub fn with_connection<R, F>(test: F)
+where
+    F: Fn(&Strong<dyn IDiceDevice>) -> Result<R>,
+{
+    let instances = get_aidl_instances(DICE_DEVICE_SERVICE_NAME, 1, DICE_DEVICE_INTERFACE_NAME);
+    let panic_hook = Arc::new(std::panic::take_hook());
+    for i in instances.into_iter() {
+        let panic_hook_clone = panic_hook.clone();
+        let instance_clone = i.clone();
+        std::panic::set_hook(Box::new(move |v| {
+            println!("While testing instance: \"{}\"", instance_clone);
+            panic_hook_clone(v)
+        }));
+        let connection: Strong<dyn IDiceDevice> = binder::get_interface(&format!(
+            "{}.{}/{}",
+            DICE_DEVICE_SERVICE_NAME, DICE_DEVICE_INTERFACE_NAME, i
+        ))
+        .unwrap();
+        test(&connection).unwrap();
+        drop(std::panic::take_hook());
+    }
+    // Cannot call unwrap here because the panic hook is not Debug.
+    std::panic::set_hook(match Arc::try_unwrap(panic_hook) {
+        Ok(hook) => hook,
+        _ => panic!("Failed to unwrap and reset previous panic hook."),
+    })
+}
diff --git a/security/keymint/aidl/Android.bp b/security/keymint/aidl/Android.bp
index 694ce6a..c9ee1b3 100644
--- a/security/keymint/aidl/Android.bp
+++ b/security/keymint/aidl/Android.bp
@@ -14,13 +14,12 @@
         "android/hardware/security/keymint/*.aidl",
     ],
     imports: [
-        "android.hardware.security.secureclock",
+        "android.hardware.security.secureclock-V1",
     ],
     stability: "vintf",
     backend: {
         java: {
             platform_apis: true,
-            srcs_available: true,
         },
         ndk: {
             vndk: {
@@ -30,7 +29,45 @@
         },
         rust: {
             enabled: true,
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.compos",
+            ],
         },
     },
     versions: ["1"],
 }
+
+// cc_defaults that includes the latest KeyMint AIDL library.
+// Modules that depend on KeyMint directly can include this cc_defaults to avoid
+// managing dependency versions explicitly.
+cc_defaults {
+    name: "keymint_use_latest_hal_aidl_ndk_static",
+    static_libs: [
+        "android.hardware.security.keymint-V2-ndk",
+    ],
+}
+
+cc_defaults {
+    name: "keymint_use_latest_hal_aidl_ndk_shared",
+    shared_libs: [
+        "android.hardware.security.keymint-V2-ndk",
+    ],
+}
+
+cc_defaults {
+    name: "keymint_use_latest_hal_aidl_cpp_static",
+    static_libs: [
+        "android.hardware.security.keymint-V2-cpp",
+    ],
+}
+
+// A rust_defaults that includes the latest KeyMint AIDL library.
+// Modules that depend on KeyMint directly can include this cc_defaults to avoid
+// managing dependency versions explicitly.
+rust_defaults {
+    name: "keymint_use_latest_hal_aidl_rust",
+    rustlibs: [
+        "android.hardware.security.keymint-V2-rust",
+    ],
+}
diff --git a/security/keymint/aidl/OWNERS b/security/keymint/aidl/OWNERS
deleted file mode 100644
index a93b171..0000000
--- a/security/keymint/aidl/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-jbires@google.com
-jdanis@google.com
-seleneh@google.com
-swillden@google.com
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/EcCurve.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/EcCurve.aidl
index 6b4a9ae..ffc7efe 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/EcCurve.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/EcCurve.aidl
@@ -39,4 +39,5 @@
   P_256 = 1,
   P_384 = 2,
   P_521 = 3,
+  CURVE_25519 = 4,
 }
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl
index fa643fc..dcc22c4 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl
@@ -49,5 +49,8 @@
   void earlyBootEnded();
   byte[] convertStorageKeyToEphemeral(in byte[] storageKeyBlob);
   android.hardware.security.keymint.KeyCharacteristics[] getKeyCharacteristics(in byte[] keyBlob, in byte[] appId, in byte[] appData);
+  byte[16] getRootOfTrustChallenge();
+  byte[] getRootOfTrust(in byte[16] challenge);
+  void sendRootOfTrust(in byte[] rootOfTrust);
   const int AUTH_TOKEN_MAC_LENGTH = 32;
 }
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/RpcHardwareInfo.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/RpcHardwareInfo.aidl
index 06bce19..5ff45f8 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/RpcHardwareInfo.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/RpcHardwareInfo.aidl
@@ -38,6 +38,7 @@
   int versionNumber;
   @utf8InCpp String rpcAuthorName;
   int supportedEekCurve = 0;
+  @nullable @utf8InCpp String uniqueId;
   const int CURVE_NONE = 0;
   const int CURVE_P256 = 1;
   const int CURVE_25519 = 2;
diff --git a/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl b/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
index b0761bf..abb2a7b 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
@@ -27,29 +27,29 @@
 @VintfStability
 parcelable DeviceInfo {
     /**
-     * DeviceInfo is a CBOR Map structure described by the following CDDL.
+     * DeviceInfo is a CBOR Map structure described by the following CDDL. DeviceInfo must be
+     * canonicalized according to the specification in RFC 7049. The ordering presented here is
+     * non-canonical to group similar entries semantically.
      *
      *     DeviceInfo = {
-     *         ? "brand" : tstr,
-     *         ? "manufacturer" : tstr,
-     *         ? "product" : tstr,
-     *         ? "model" : tstr,
-     *         ? "board" : 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
-     *         ? "system_patch_level" : uint,                   // YYYYMMDD
-     *         ? "boot_patch_level" : uint,                     // YYYYMMDD
-     *         ? "vendor_patch_level" : uint,                   // YYYYMMDD
-     *         "version" : 1,                      // The CDDL schema version.
-     *         "security_level" : "tee" / "strongbox"
-     *         "att_id_state": "locked" / "open",  // Attestation IDs State. If "locked", this
-     *                                             // indicates a device's attestable IDs are
-     *                                             // factory-locked and immutable. If "open",
-     *                                             // this indicates the device is still in a
-     *                                             // provisionable state and the attestable IDs
-     *                                             // are not yet frozen.
+     *         "brand" : tstr,
+     *         "manufacturer" : tstr,
+     *         "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.
+     *         "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.
      *     }
      */
     byte[] deviceInfo;
diff --git a/security/keymint/aidl/android/hardware/security/keymint/EcCurve.aidl b/security/keymint/aidl/android/hardware/security/keymint/EcCurve.aidl
index 5b1c10c..e9f81d8 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/EcCurve.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/EcCurve.aidl
@@ -27,4 +27,5 @@
     P_256 = 1,
     P_384 = 2,
     P_521 = 3,
+    CURVE_25519 = 4,
 }
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
index 4e81e71..b9694e9 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
@@ -93,6 +93,13 @@
  *        P-521.  STRONGBOX IKeyMintDevices must support NIST curve P-256.
  *      - TRUSTED_ENVIRONMENT IKeyMintDevices must support SHA1, SHA-2 224, SHA-2 256, SHA-2
  *        384 and SHA-2 512 digest modes.  STRONGBOX IKeyMintDevices must support SHA-2 256.
+ *      - TRUSTED_ENVRIONMENT IKeyMintDevices must support curve 25519 for Purpose::SIGN (Ed25519,
+ *        as specified in RFC 8032), Purpose::ATTEST_KEY (Ed25519) or for KeyPurpose::AGREE_KEY
+ *        (X25519, as specified in RFC 7748).  However, a key must have exactly one of these
+ *        purpose values; the same key cannot be used for multiple purposes. Signing operations
+ *        (Purpose::SIGN) have a message size limit of 16 KiB; operations on messages longer than
+ *        this limit must fail with ErrorCode::INVALID_INPUT_LENGTH.
+ *        STRONGBOX IKeyMintDevices do not support curve 25519.
  *
  * o   AES
  *
@@ -189,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 ==
  *
@@ -234,8 +241,6 @@
      * indistinguishable from random.  Thus, if the entropy from any source is good, the output
      * must be good.
      *
-     * TODO(seleneh) specify what mixing functions and cprng we allow.
-     *
      * @param data Bytes to be mixed into the CRNG seed.  The caller must not provide more than 2
      *        KiB of data per invocation.
      *
@@ -289,7 +294,7 @@
      *   except AGREE_KEY must be supported for RSA keys.
      *
      * o Tag::DIGEST specifies digest algorithms that may be used with the new key.  TEE
-     *   IKeyMintDevice implementations must support all Digest values (see digest.aidl) for RSA
+     *   IKeyMintDevice implementations must support all Digest values (see Digest.aidl) for RSA
      *   keys.  StrongBox IKeyMintDevice implementations must support SHA_2_256.
      *
      * o Tag::PADDING specifies the padding modes that may be used with the new
@@ -300,13 +305,24 @@
      * == ECDSA Keys ==
      *
      * Tag::EC_CURVE must be provided to generate an ECDSA key.  If it is not provided, generateKey
-     * must return ErrorCode::UNSUPPORTED_KEY_SIZE. TEE IKeyMintDevice implementations must support
-     * all curves.  StrongBox implementations must support P_256.
-
+     * must return ErrorCode::UNSUPPORTED_KEY_SIZE or ErrorCode::UNSUPPORTED_EC_CURVE. TEE
+     * IKeyMintDevice implementations must support all required curves.  StrongBox implementations
+     * must support P_256 and no other curves.
+     *
      * Tag::CERTIFICATE_NOT_BEFORE and Tag::CERTIFICATE_NOT_AFTER must be provided to specify the
      * valid date range for the returned X.509 certificate holding the public key. If omitted,
      * generateKey must return ErrorCode::MISSING_NOT_BEFORE or ErrorCode::MISSING_NOT_AFTER.
      *
+     * Keys with EC_CURVE of EcCurve::CURVE_25519 must have exactly one purpose in the set
+     * {KeyPurpose::SIGN, KeyPurpose::ATTEST_KEY, KeyPurpose::AGREE_KEY}.  Key generation with more
+     * than one purpose should be rejected with ErrorCode::INCOMPATIBLE_PURPOSE.
+     * StrongBox implementation do not support CURVE_25519.
+     *
+     * Tag::DIGEST specifies digest algorithms that may be used with the new key.  TEE
+     * IKeyMintDevice implementations must support all Digest values (see Digest.aidl) for ECDSA
+     * keys; Ed25519 keys only support Digest::NONE. StrongBox IKeyMintDevice implementations must
+     * support SHA_2_256.
+     *
      * == AES Keys ==
      *
      * Only Tag::KEY_SIZE is required to generate an AES key.  If omitted, generateKey must return
@@ -835,4 +851,82 @@
      */
     KeyCharacteristics[] getKeyCharacteristics(
             in byte[] keyBlob, in byte[] appId, in byte[] appData);
+
+    /**
+     * Returns a 16-byte random challenge nonce, used to prove freshness when exchanging root of
+     * trust data.
+     *
+     * This method may only be implemented by StrongBox KeyMint.  TEE KeyMint implementations must
+     * return ErrorCode::UNIMPLEMENTED.  StrongBox KeyMint implementations MAY return UNIMPLEMENTED,
+     * to indicate that they have an alternative mechanism for getting the data.  If the StrongBox
+     * implementation returns UNIMPLEMENTED, the client should not call `getRootofTrust()` or
+     * `sendRootOfTrust()`.
+     */
+    byte[16] getRootOfTrustChallenge();
+
+    /**
+     * Returns the TEE KeyMint Root of Trust data.
+     *
+     * This method is required for TEE KeyMint.  StrongBox KeyMint implementations MUST return
+     * ErrorCode::UNIMPLEMENTED.
+     *
+     * The returned data is an encoded COSE_Mac0 structure, denoted MacedRootOfTrust in the
+     * following CDDL schema.  Note that K_mac is the shared HMAC key used for auth tokens, etc.:
+     *
+     *     MacedRootOfTrust = #6.17 [         ; COSE_Mac0 (tagged)
+     *         protected: bstr .cbor {
+     *             1 : 5,                     ; Algorithm : HMAC-256
+     *         },
+     *         unprotected : {},
+     *         payload : bstr .cbor RootOfTrust,
+     *         tag : bstr HMAC-256(K_mac, MAC_structure)
+     *     ]
+     *
+     *     MAC_structure = [
+     *         context : "MAC0",
+     *         protected : bstr .cbor {
+     *             1 : 5,                     ; Algorithm : HMAC-256
+     *         },
+     *         external_aad : bstr .size 16   ; Value of challenge argument
+     *         payload : bstr .cbor RootOfTrust,
+     *     ]
+     *
+     *     RootOfTrust = #6.40001 [           ; Tag 40001 indicates RoT v1.
+     *         verifiedBootKey : bstr .size 32,
+     *         deviceLocked : bool,
+     *         verifiedBootState : &VerifiedBootState,
+     *         verifiedBootHash : bstr .size 32,
+     *         bootPatchLevel : int,          ; See Tag::BOOT_PATCHLEVEL
+     *     ]
+     *
+     *     VerifiedBootState = (
+     *         Verified : 0,
+     *         SelfSigned : 1,
+     *         Unverified : 2,
+     *         Failed : 3
+     *     )
+     */
+    byte[] getRootOfTrust(in byte[16] challenge);
+
+    /**
+     * Delivers the TEE KeyMint Root of Trust data to StrongBox KeyMint.  See `getRootOfTrust()`
+     * above for specification of the data format and cryptographic security structure.
+     *
+     * The implementation must verify the MAC on the RootOfTrust data.  If it is valid, and if this
+     * is the first time since reboot that StrongBox KeyMint has received this data, it must store
+     * the RoT data for use in key attestation requests, then return ErrorCode::ERROR_OK.
+     *
+     * If the MAC on the Root of Trust data and challenge is incorrect, the implementation must
+     * return ErrorCode::VERIFICATION_FAILED.
+     *
+     * If the RootOfTrust data has already been received since the last boot, the implementation
+     * must validate the data and return ErrorCode::VERIFICATION_FAILED or ErrorCode::ERROR_OK
+     * according to the result, but must not store the data for use in key attestation requests,
+     * even if verification succeeds.  On success, the challenge is invalidated and a new challenge
+     * must be requested before the RootOfTrust data may be sent again.
+     *
+     * This method is optional for StrongBox KeyMint, which MUST return ErrorCode::UNIMPLEMENTED if
+     * not implemented.  TEE KeyMint implementations must return ErrorCode::UNIMPLEMENTED.
+     */
+    void sendRootOfTrust(in byte[] rootOfTrust);
 }
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
index aa7b492..c30c183 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
@@ -155,8 +155,7 @@
      * it must process all but the tag length and buffer the possible tag data for processing during
      * finish().
      *
-     * @param input Data to be processed.  Note that update() may or may not consume all of the data
-     *        provided.  See return value.
+     * @param input Data to be processed.  update() must consume all input data.
      *
      * @param authToken Authentication token. Can be nullable if not provided.
      *
@@ -228,7 +227,8 @@
      * o PaddingMode::RSA_PSS.  For PSS-padded signature operations, the PSS salt length must match
      *   the size of the PSS digest selected.  The digest specified with Tag::DIGEST in params
      *   on begin() must be used as the PSS digest algorithm, MGF1 must be used as the mask
-     *   generation function and SHA1 must be used as the MGF1 digest algorithm.
+     *   generation function and the digest specified with Tag:DIGEST in params on begin() must also
+     *   be used as the MGF1 digest algorithm.
      *
      * -- ECDSA keys --
      *
@@ -242,7 +242,8 @@
      *   not a multiple of the AES block size, finish() must return
      *   ErrorCode::INVALID_INPUT_LENGTH.  If padding is PaddingMode::PKCS7, pad the data per the
      *   PKCS#7 specification, including adding an additional padding block if the data is a
-     *   multiple of the block length.
+     *   multiple of the block length.  If padding is PaddingMode::PKCS7 and decryption does not
+     *   result in valid padding, return ErrorCode::INVALID_ARGUMENT.
      *
      * o BlockMode::GCM.  During encryption, after processing all plaintext, compute the tag
      *   (Tag::MAC_LENGTH bytes) and append it to the returned ciphertext.  During decryption,
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyCharacteristics.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyCharacteristics.aidl
index 25fdee3..f0df048 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyCharacteristics.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyCharacteristics.aidl
@@ -32,6 +32,17 @@
  */
 @VintfStability
 parcelable KeyCharacteristics {
+    /**
+     * The security level enforcing this collection of key properties.
+     */
     SecurityLevel securityLevel = SecurityLevel.SOFTWARE;
+
+    /**
+     * `authorizations` is a list of key properties that are enforced at this security level.
+     * A key can have different properties enforced by components of different security levels.
+     * For example, some properties are provided by the operating system, which has a
+     * different security level to the IKeyMintDevice.
+     * See the `keyCharacteristics` field in `KeyCreationResult` for more details.
+     */
     KeyParameter[] authorizations;
 }
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
index fd6bf65..57285a3 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
@@ -61,13 +61,15 @@
      * the non-attestation case, whether the key can self-sign.
      *
      * 1.  Asymmetric key attestation with factory key.  If Tag::ATTESTATION_CHALLENGE is provided
-     *     and the `attestationKey` parameter on the generate/import call is null, the returned
+     *     and the `attestationKey` parameter on the generate/import call is null, and if the
+     *     KeyMint implementation supports factory-provisioned attestation keys, the returned
      *     certificate chain must contain an attestation certificate signed with a factory-
      *     provisioned attestation key, and the full certificate chain for that factory-provisioned
      *     attestation key.  Tag::ATTESTATION_APPLICATION_ID must also be provided when the
      *     ATTESTATION_CHALLENGE is provided, otherwise ATTESTATION_APPLICATION_ID_MISSING will be
      *     returned.  KeyMint implementations are not required to support factory-provisioned
-     *     attestation keys.
+     *     attestation keys. If the KeyMint implementation does not support factory-provisioned
+     *     keys, it must return ATTESTATION_KEYS_NOT_PROVISIONED.
      *
      * 2.  Asymmetric key attestation with caller-provided key.  If Tag::ATTESTATION_CHALLENGE is
      *     provided and the `attestationKey` parameter on the generate/import call is non-null and
@@ -78,15 +80,16 @@
      *     provided, otherwise ATTESTATION_APPLICATION_ID_MISSING will be returned.
      *
      * 3.  Asymmetric key non-attestation with signing key.  If Tag::ATTESTATION_CHALLENGE is not
-     *     provided and the generated/imported key has KeyPurpose::SIGN, then the returned
-     *     certificate chain must contain only a single self-signed certificate with no attestation
-     *     extension.  Tag::ATTESTATION_APPLICATION_ID will be ignored if provided.
+     *     provided and the generated/imported key has KeyPurpose::SIGN or KeyPurpose::ATTEST_KEY,
+     *     then the returned certificate chain must contain only a single self-signed certificate
+     *     with no attestation extension.  Tag::ATTESTATION_APPLICATION_ID will be ignored if
+     *     provided.
      *
      * 4.  Asymmetric key non-attestation with non-signing key.  If TAG::ATTESTATION_CHALLENGE is
-     *     not provided and the generated/imported key does not have KeyPurpose::SIGN, then the
-     *     returned certificate chain must contain only a single certificate with an empty signature
-     *     and no attestation extension.  Tag::ATTESTATION_APPLICATION_ID will be ignored if
-     *     provided.
+     *     not provided and the generated/imported key does not have KeyPurpose::SIGN nor
+     *     KeyPurpose::ATTEST_KEY, then the returned certificate chain must contain only a single
+     *     certificate with an empty signature and no attestation extension.
+     *     Tag::ATTESTATION_APPLICATION_ID will be ignored if provided.
      *
      * 5.  Symmetric key.  If the generated/imported key is symmetric, the certificate chain must
      *     return empty, any Tag::ATTESTATION_CHALLENGE or Tag::ATTESTATION_APPLICATION_ID inputs,
@@ -122,9 +125,9 @@
      * straightforward translation of the KeyMint tag/value parameter lists to ASN.1.
      *
      * KeyDescription ::= SEQUENCE {
-     *     attestationVersion         INTEGER, # Value 100
+     *     attestationVersion         INTEGER, # Value 200
      *     attestationSecurityLevel   SecurityLevel, # See below
-     *     keyMintVersion             INTEGER, # Value 100
+     *     keyMintVersion             INTEGER, # Value 200
      *     keymintSecurityLevel       SecurityLevel, # See below
      *     attestationChallenge       OCTET_STRING, # Tag::ATTESTATION_CHALLENGE from attestParams
      *     uniqueId                   OCTET_STRING, # Empty unless key has Tag::INCLUDE_UNIQUE_ID
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyFormat.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyFormat.aidl
index da3d521..3faef38 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyFormat.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyFormat.aidl
@@ -25,8 +25,10 @@
 enum KeyFormat {
     /** X.509 certificate format, for public key export. */
     X509 = 0,
-    /** PCKS#8 format, asymmetric key pair import. */
+    /** PKCS#8 format, asymmetric key pair import. */
     PKCS8 = 1,
-    /** Raw bytes, for symmetric key import. */
+    /**
+     * Raw bytes, for symmetric key import, and for import of raw asymmetric keys for curve 25519.
+     */
     RAW = 3,
 }
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyMintHardwareInfo.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyMintHardwareInfo.aidl
index 8da7578..b82dee6 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyMintHardwareInfo.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyMintHardwareInfo.aidl
@@ -29,7 +29,6 @@
      * Implementation version of the keymint hardware.  The version number is implementation
      * defined, and not necessarily globally meaningful.  The version is used to distinguish
      * between different versions of a given implementation.
-     * TODO(seleneh) add the version related info to the code.
      */
     int versionNumber;
 
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyPurpose.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyPurpose.aidl
index e141e55..fd103ef 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyPurpose.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyPurpose.aidl
@@ -44,6 +44,10 @@
     AGREE_KEY = 6,
 
     /* Usable as an attestation signing key.  Keys with this purpose must not have any other
-     * purpose. */
+     * purpose; if they do, key generation/import must be rejected with
+     * ErrorCode::INCOMPATIBLE_PURPOSE. (Rationale: If key also included KeyPurpose::SIGN, then
+     * it could be used to sign arbitrary data, including any tbsCertificate, and so an
+     * attestation produced by the key would have no security properties.)
+     */
     ATTEST_KEY = 7,
 }
diff --git a/security/keymint/aidl/android/hardware/security/keymint/MacedPublicKey.aidl b/security/keymint/aidl/android/hardware/security/keymint/MacedPublicKey.aidl
index 62a48e9..ad97443 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/MacedPublicKey.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/MacedPublicKey.aidl
@@ -37,10 +37,10 @@
      *
      *     PublicKey = {               // COSE_Key
      *         1 : 2,                  // Key type : EC2
-     *         3 : -8                  // Algorithm : ES256
-     *         -1 : 6,                 // Curve : P256
-     *         -2 : bstr               // X coordinate, little-endian
-     *         -3 : bstr               // Y coordinate, little-endian
+     *         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.
      *     },
diff --git a/security/keymint/aidl/android/hardware/security/keymint/PaddingMode.aidl b/security/keymint/aidl/android/hardware/security/keymint/PaddingMode.aidl
index fbb373b..e71a9c9 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/PaddingMode.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/PaddingMode.aidl
@@ -17,8 +17,6 @@
 package android.hardware.security.keymint;
 
 /**
- * TODO(seleneh) update the description.
- *
  * Padding modes that may be applied to plaintext for encryption operations.  This list includes
  * padding modes for both symmetric and asymmetric algorithms.  Note that implementations should not
  * provide all possible combinations of algorithm and padding, only the
diff --git a/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl b/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl
index 24cdbc1..8b3875b 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl
@@ -18,13 +18,20 @@
 
 /**
  * ProtectedData contains the encrypted BCC and the ephemeral MAC key used to
- * authenticate the keysToSign (see keysToSignMac output argument).
+ * authenticate the keysToSign (see keysToSignMac output argument of
+ * IRemotelyProvisionedComponent.generateCertificateRequest).
  * @hide
  */
 @VintfStability
 parcelable ProtectedData {
     /**
-     * ProtectedData is a COSE_Encrypt structure, specified by the following CDDL
+     * ProtectedData is a COSE_Encrypt structure, encrypted with an AES key that is agreed upon
+     * using Elliptic-curve Diffie-Hellman. The contents of the structure are specified by the
+     * following CDDL [RFC8610].
+     *
+     * Notes:
+     *   - None of the CBOR in ProtectedData uses CBOR tags. If an implementation includes
+     *     tags, parsers may reject the data.
      *
      *     ProtectedData = [               // COSE_Encrypt
      *         protected: bstr .cbor {
@@ -34,13 +41,18 @@
      *             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)
      *         recipients : [
      *             [                       // COSE_Recipient
      *                 protected : bstr .cbor {
      *                     1 : -25         // Algorithm : ECDH-ES + HKDF-256
      *                 },
      *                 unprotected : {
-     *                     -1 : PubKeyX25519 / PubKeyEcdhP256  // Of the sender
+     *                     -1 : PubKeyX25519 / PubKeyEcdhP256  // Ephemeral_pub
      *                     4 : bstr,       // KID : EEK ID
      *                 },
      *                 ciphertext : nil
@@ -48,14 +60,14 @@
      *         ]
      *     ]
      *
-     *     K = HKDF-256(ECDH(EEK_pub, Ephemeral_priv), Context)
-     *
-     *     Context = [                     // COSE_KDF_Context
+     *     // 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
      *         PartyUInfo : [
      *             identity : bstr "client"
      *             nonce : bstr .size 0,
-     *             other : bstr            // Ephemeral pubkey
+     *             other : bstr            // Ephemeral_pub
      *         ],
      *         PartyVInfo : [
      *             identity : bstr "server",
@@ -68,84 +80,114 @@
      *         ]
      *     ]
      *
+     *     // 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 = {
      *         + SignerName => DKCertChain
      *     }
      *
+     *     // SignerName is a string identifier that indicates both the signing authority as
+     *     // well as the format of the DKCertChain
      *     SignerName = tstr
      *
      *     DKCertChain = [
-     *         2* Certificate                      // Root -> Leaf.  Root is the vendor
-     *                                             // self-signed cert, leaf contains DK_pub
+     *         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.
      *     ]
      *
-     *     Certificate = COSE_Sign1 of a public key
+     *     // A bstr containing a DER-encoded X.509 certificate (RSA, NIST P-curve, or edDSA)
+     *     X509Certificate = bstr
      *
-     *     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,                  // MAC key
-     *         bstr PureEd25519(KM_priv, .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 = [
+     *     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 .cbor SignedMacAad,
+     *         bstr .size 32                            // MAC key
      *     ]
      *
      *     SignedMacAad = [
-     *         challenge : bstr,
+     *         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.
      *     ]
      *
+     *     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.
      *     Bcc = [
      *         PubKeyEd25519 / PubKeyECDSA256, // DK_pub
      *         + BccEntry,                     // Root -> leaf (KM_pub)
      *     ]
      *
-     *     BccPayload = {                     // CWT
-     *         1 : tstr,                      // Issuer
-     *         2 : tstr,                      // Subject
-     *         // See the Open Profile for DICE for details on these fields.
-     *         ? -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
+     *     // 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
+     *         },
+     *         -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)
      *         protected : bstr .cbor {
      *             1 : AlgorithmEdDSA / AlgorithmES256,  // Algorithm
      *         },
      *         unprotected: {},
      *         payload: bstr .cbor BccPayload,
-     *         signature: bstr .cbor PureEd25519(SigningKey, bstr .cbor BccEntryInput) /
-     *                    bstr .cbor ECDSA(SigningKey, bstr .cbor BccEntryInput)
+     *         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.
      *     ]
      *
@@ -158,8 +200,8 @@
      *         payload: bstr .cbor BccPayload
      *     ]
      *
-     *     VerifiedDeviceInfo = DeviceInfo  // See DeviceInfo.aidl
-     *
+     *     // 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
@@ -167,27 +209,25 @@
      *     }
      *
      *     PubKeyEd25519 = {                // COSE_Key
-     *         1 : 1,                         // Key type : octet key pair
-     *         3 : AlgorithmEdDSA,            // Algorithm : EdDSA
-     *         4 : 2,                         // Ops: Verify
-     *         -1 : 6,                        // Curve : Ed25519
-     *         -2 : bstr                      // X coordinate, little-endian
+     *         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
-     *         4 : 2,                         // Ops: Verify
-     *         -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/RpcHardwareInfo.aidl b/security/keymint/aidl/android/hardware/security/keymint/RpcHardwareInfo.aidl
index d297f87..0cb33ce 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/RpcHardwareInfo.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/RpcHardwareInfo.aidl
@@ -53,4 +53,25 @@
      * a passing implementation does not provide CURVE_NONE.
      */
     int supportedEekCurve = CURVE_NONE;
+
+    /**
+     * uniqueId is an opaque identifier for this IRemotelyProvisionedComponent implementation. The
+     * client should NOT interpret the content of the identifier in any way. The client can only
+     * compare identifiers to determine if two IRemotelyProvisionedComponents share the same
+     * implementation. Each IRemotelyProvisionedComponent implementation must have a distinct
+     * identifier from all other implementations, and it must be consistent across all devices.
+     * It's critical that this identifier not be usable to uniquely identify a specific device.
+     *
+     * This identifier must be consistent across reboots, as it is used to store and track
+     * provisioned keys in a persistent, on-device database.
+     *
+     * uniqueId may not be empty, and must not be any longer than 32 characters.
+     *
+     * A recommended construction for this value is "[Vendor] [Component Name] [Major Version]",
+     * e.g. "Google Trusty KeyMint 1".
+     *
+     * This field was added in API version 2.
+     *
+     */
+    @nullable @utf8InCpp String uniqueId;
 }
diff --git a/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl b/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
index 67a0214..42dfad5 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
@@ -268,10 +268,6 @@
     USAGE_EXPIRE_DATETIME = TagType.DATE | 402,
 
     /**
-     * TODO(seleneh) this tag need to be deleted.
-     *
-     * TODO(seleneh) this tag need to be deleted.
-     *
      * 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.
@@ -508,7 +504,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
@@ -529,7 +527,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
@@ -831,7 +831,7 @@
     /**
      * DEVICE_UNIQUE_ATTESTATION is an argument to IKeyMintDevice::attested key generation/import
      * operations.  It indicates that attestation using a device-unique key is requested, rather
-     * than a batch key. When a device-unique key is used, the returned chain contains two or
+     * than a batch key. When a device-unique key is used, the returned chain should contain two or
      * three certificates.
      *
      * In case the chain contains two certificates, they should be:
@@ -844,7 +844,8 @@
      *      KeyCreationResult.aidl, signed by the device-unique key.
      *    * An intermediate certificate, containing the public portion of the device-unique key.
      *    * A self-signed root certificate, signed by a dedicated key, certifying the
-     *      intermediate.
+     *      intermediate. Ideally, the dedicated key would be the same for all StrongBox
+     *      instances of the same manufacturer to ease validation.
      *
      * No additional chained certificates are provided. Only SecurityLevel::STRONGBOX
      * IKeyMintDevices may support device-unique attestations.  SecurityLevel::TRUSTED_ENVIRONMENT
diff --git a/security/keymint/aidl/default/Android.bp b/security/keymint/aidl/default/Android.bp
index 230534c..1a17fd4 100644
--- a/security/keymint/aidl/default/Android.bp
+++ b/security/keymint/aidl/default/Android.bp
@@ -21,10 +21,12 @@
         "-Wall",
         "-Wextra",
     ],
+    defaults: [
+        "keymint_use_latest_hal_aidl_ndk_shared",
+    ],
     shared_libs: [
-        "android.hardware.security.keymint-V1-ndk_platform",
-        "android.hardware.security.sharedsecret-V1-ndk_platform",
-        "android.hardware.security.secureclock-V1-ndk_platform",
+        "android.hardware.security.sharedsecret-V1-ndk",
+        "android.hardware.security.secureclock-V1-ndk",
         "libbase",
         "libbinder_ndk",
         "libcppbor_external",
diff --git a/security/keymint/aidl/default/TEST_MAPPING b/security/keymint/aidl/default/TEST_MAPPING
new file mode 100644
index 0000000..2400ccd
--- /dev/null
+++ b/security/keymint/aidl/default/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit" : [
+    {
+      "name" : "vts_treble_vintf_framework_test"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/security/keymint/aidl/default/android.hardware.hardware_keystore.xml b/security/keymint/aidl/default/android.hardware.hardware_keystore.xml
index e5a9345..2ebf1fe 100644
--- a/security/keymint/aidl/default/android.hardware.hardware_keystore.xml
+++ b/security/keymint/aidl/default/android.hardware.hardware_keystore.xml
@@ -14,5 +14,5 @@
      limitations under the License.
 -->
 <permissions>
-  <feature name="android.hardware.hardware_keystore" version="100" />
+  <feature name="android.hardware.hardware_keystore" version="200" />
 </permissions>
diff --git a/security/keymint/aidl/default/android.hardware.security.keymint-service.xml b/security/keymint/aidl/default/android.hardware.security.keymint-service.xml
index 4aa05ef..a4d0302 100644
--- a/security/keymint/aidl/default/android.hardware.security.keymint-service.xml
+++ b/security/keymint/aidl/default/android.hardware.security.keymint-service.xml
@@ -1,10 +1,12 @@
 <manifest version="1.0" type="device">
     <hal format="aidl">
         <name>android.hardware.security.keymint</name>
+        <version>2</version>
         <fqname>IKeyMintDevice/default</fqname>
     </hal>
     <hal format="aidl">
         <name>android.hardware.security.keymint</name>
+        <version>2</version>
         <fqname>IRemotelyProvisionedComponent/default</fqname>
     </hal>
 </manifest>
diff --git a/security/keymint/aidl/default/service.cpp b/security/keymint/aidl/default/service.cpp
index 8092e34..dc0c618 100644
--- a/security/keymint/aidl/default/service.cpp
+++ b/security/keymint/aidl/default/service.cpp
@@ -39,7 +39,7 @@
     LOG(INFO) << "adding keymint service instance: " << instanceName;
     binder_status_t status =
             AServiceManager_addService(ser->asBinder().get(), instanceName.c_str());
-    CHECK(status == STATUS_OK);
+    CHECK_EQ(status, STATUS_OK);
     return ser;
 }
 
diff --git a/security/keymint/aidl/vts/functional/Android.bp b/security/keymint/aidl/vts/functional/Android.bp
index 77eea8a..ef5b0bd 100644
--- a/security/keymint/aidl/vts/functional/Android.bp
+++ b/security/keymint/aidl/vts/functional/Android.bp
@@ -26,6 +26,7 @@
 cc_defaults {
     name: "keymint_vts_defaults",
     defaults: [
+        "keymint_use_latest_hal_aidl_ndk_static",
         "use_libaidlvintf_gtest_helper_static",
         "VtsHalTargetTestDefaults",
     ],
@@ -34,8 +35,7 @@
         "libcrypto",
     ],
     static_libs: [
-        "android.hardware.security.keymint-V1-ndk_platform",
-        "android.hardware.security.secureclock-V1-ndk_platform",
+        "android.hardware.security.secureclock-V1-ndk",
         "libcppbor_external",
         "libcppcose_rkp",
         "libjsoncpp",
@@ -50,10 +50,14 @@
     defaults: [
         "keymint_vts_defaults",
     ],
+    tidy_timeout_srcs: [
+        "KeyMintTest.cpp",
+    ],
     srcs: [
         "AttestKeyTest.cpp",
         "DeviceUniqueAttestationTest.cpp",
         "KeyMintTest.cpp",
+        "SecureElementProvisioningTest.cpp",
     ],
     static_libs: [
         "libkeymint_vts_test_utils",
@@ -69,12 +73,18 @@
     defaults: [
         "keymint_vts_defaults",
     ],
+    tidy_timeout_srcs: [
+        "KeyMintAidlTestBase.cpp",
+    ],
     srcs: [
         "KeyMintAidlTestBase.cpp",
     ],
     export_include_dirs: [
         ".",
     ],
+    export_static_lib_headers: [
+        "libkeymint_support",
+    ],
     static_libs: [
         "libgmock_ndk",
     ],
diff --git a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
index 64550ef..240de35 100644
--- a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
+++ b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
@@ -81,7 +81,8 @@
 
         AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
         AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
-        EXPECT_TRUE(verify_attestation_record("foo", "bar", sw_enforced, hw_enforced, SecLevel(),
+        EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
+                                              SecLevel(),
                                               attested_key_cert_chain[0].encodedCertificate));
 
         // Attestation by itself is not valid (last entry is not self-signed).
@@ -113,7 +114,8 @@
 
         hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
         sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
-        EXPECT_TRUE(verify_attestation_record("foo2", "bar2", sw_enforced, hw_enforced, SecLevel(),
+        EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo2", "bar2", sw_enforced,
+                                              hw_enforced, SecLevel(),
                                               attested_key_cert_chain[0].encodedCertificate));
 
         // Attestation by itself is not valid (last entry is not self-signed).
@@ -154,12 +156,13 @@
         sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
 
         // The client-specified CREATION_DATETIME should be in sw_enforced.
-        // Its presence will also trigger verify_attestation_record() to check that it
-        // is in the attestation extension with a matching value.
+        // Its presence will also trigger verify_attestation_record() to check that
+        // it is in the attestation extension with a matching value.
         EXPECT_TRUE(sw_enforced.Contains(TAG_CREATION_DATETIME, timestamp))
                 << "expected CREATION_TIMESTAMP in sw_enforced:" << sw_enforced
                 << " not in hw_enforced:" << hw_enforced;
-        EXPECT_TRUE(verify_attestation_record("foo", "bar", sw_enforced, hw_enforced, SecLevel(),
+        EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
+                                              SecLevel(),
                                               attested_key_cert_chain[0].encodedCertificate));
 
         // Attestation by itself is not valid (last entry is not self-signed).
@@ -175,6 +178,32 @@
 }
 
 /*
+ * AttestKeyTest.RsaAttestKeyMultiPurposeFail
+ *
+ * This test attempts to create an RSA attestation key that also allows signing.
+ */
+TEST_P(AttestKeyTest, RsaAttestKeyMultiPurposeFail) {
+    if (AidlVersion() < 2) {
+        // The KeyMint v1 spec required that KeyPurpose::ATTEST_KEY not be combined
+        // with other key purposes.  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() << "Single-purpose for KeyPurpose::ATTEST_KEY only strict since KeyMint v2";
+    }
+
+    vector<uint8_t> attest_key_blob;
+    vector<KeyCharacteristics> attest_key_characteristics;
+    vector<Certificate> attest_key_cert_chain;
+    ASSERT_EQ(ErrorCode::INCOMPATIBLE_PURPOSE,
+              GenerateKey(AuthorizationSetBuilder()
+                                  .RsaSigningKey(2048, 65537)
+                                  .AttestKey()
+                                  .SetDefaultValidity(),
+                          {} /* attestation signing key */, &attest_key_blob,
+                          &attest_key_characteristics, &attest_key_cert_chain));
+}
+
+/*
  * AttestKeyTest.RsaAttestedAttestKeys
  *
  * This test creates an RSA attestation key signed by factory keys, and varifies it can be
@@ -198,18 +227,22 @@
     AttestationKey attest_key;
     vector<KeyCharacteristics> attest_key_characteristics;
     vector<Certificate> attest_key_cert_chain;
-    ASSERT_EQ(ErrorCode::OK,
-              GenerateKey(AuthorizationSetBuilder()
-                                  .RsaKey(2048, 65537)
-                                  .AttestKey()
-                                  .AttestationChallenge(challenge)
-                                  .AttestationApplicationId(app_id)
-                                  .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
-                                  .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
-                                  .Authorization(TAG_NO_AUTH_REQUIRED)
-                                  .SetDefaultValidity(),
-                          {} /* attestation signing key */, &attest_key.keyBlob,
-                          &attest_key_characteristics, &attest_key_cert_chain));
+    auto result = GenerateKey(AuthorizationSetBuilder()
+                                      .RsaKey(2048, 65537)
+                                      .AttestKey()
+                                      .AttestationChallenge(challenge)
+                                      .AttestationApplicationId(app_id)
+                                      .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+                                      .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+                                      .Authorization(TAG_NO_AUTH_REQUIRED)
+                                      .SetDefaultValidity(),
+                              {} /* attestation signing key */, &attest_key.keyBlob,
+                              &attest_key_characteristics, &attest_key_cert_chain);
+    // Strongbox may not support factory provisioned attestation key.
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+    }
+    ASSERT_EQ(ErrorCode::OK, result);
 
     EXPECT_GT(attest_key_cert_chain.size(), 1);
     verify_subject_and_serial(attest_key_cert_chain[0], serial_int, subject, false);
@@ -217,7 +250,7 @@
 
     AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attest_key_characteristics);
     AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attest_key_characteristics);
-    EXPECT_TRUE(verify_attestation_record(challenge, app_id,  //
+    EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id,  //
                                           sw_enforced, hw_enforced, SecLevel(),
                                           attest_key_cert_chain[0].encodedCertificate));
 
@@ -252,7 +285,8 @@
 
     AuthorizationSet hw_enforced2 = HwEnforcedAuthorizations(attested_key_characteristics);
     AuthorizationSet sw_enforced2 = SwEnforcedAuthorizations(attested_key_characteristics);
-    EXPECT_TRUE(verify_attestation_record("foo", "bar", sw_enforced2, hw_enforced2, SecLevel(),
+    EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced2, hw_enforced2,
+                                          SecLevel(),
                                           attested_key_cert_chain[0].encodedCertificate));
 
     // Attestation by itself is not valid (last entry is not self-signed).
@@ -297,23 +331,28 @@
             attest_key_opt = attest_key;
         }
 
-        EXPECT_EQ(ErrorCode::OK,
-                  GenerateKey(AuthorizationSetBuilder()
-                                      .RsaKey(2048, 65537)
-                                      .AttestKey()
-                                      .AttestationChallenge("foo")
-                                      .AttestationApplicationId("bar")
-                                      .Authorization(TAG_NO_AUTH_REQUIRED)
-                                      .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
-                                      .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
-                                      .SetDefaultValidity(),
-                              attest_key_opt, &key_blob_list[i], &attested_key_characteristics,
-                              &cert_chain_list[i]));
+        auto result = GenerateKey(AuthorizationSetBuilder()
+                                          .RsaKey(2048, 65537)
+                                          .AttestKey()
+                                          .AttestationChallenge("foo")
+                                          .AttestationApplicationId("bar")
+                                          .Authorization(TAG_NO_AUTH_REQUIRED)
+                                          .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+                                          .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+                                          .SetDefaultValidity(),
+                                  attest_key_opt, &key_blob_list[i], &attested_key_characteristics,
+                                  &cert_chain_list[i]);
+        // Strongbox may not support factory provisioned attestation key.
+        if (SecLevel() == SecurityLevel::STRONGBOX) {
+            if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+        }
+        ASSERT_EQ(ErrorCode::OK, result);
 
         AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
         AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
         ASSERT_GT(cert_chain_list[i].size(), 0);
-        EXPECT_TRUE(verify_attestation_record("foo", "bar", sw_enforced, hw_enforced, SecLevel(),
+        EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
+                                              SecLevel(),
                                               cert_chain_list[i][0].encodedCertificate));
 
         if (i > 0) {
@@ -369,23 +408,28 @@
             attest_key_opt = attest_key;
         }
 
-        EXPECT_EQ(ErrorCode::OK,
-                  GenerateKey(AuthorizationSetBuilder()
-                                      .EcdsaKey(EcCurve::P_256)
-                                      .AttestKey()
-                                      .AttestationChallenge("foo")
-                                      .AttestationApplicationId("bar")
-                                      .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
-                                      .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
-                                      .Authorization(TAG_NO_AUTH_REQUIRED)
-                                      .SetDefaultValidity(),
-                              attest_key_opt, &key_blob_list[i], &attested_key_characteristics,
-                              &cert_chain_list[i]));
+        auto result = GenerateKey(AuthorizationSetBuilder()
+                                          .EcdsaKey(EcCurve::P_256)
+                                          .AttestKey()
+                                          .AttestationChallenge("foo")
+                                          .AttestationApplicationId("bar")
+                                          .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+                                          .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+                                          .Authorization(TAG_NO_AUTH_REQUIRED)
+                                          .SetDefaultValidity(),
+                                  attest_key_opt, &key_blob_list[i], &attested_key_characteristics,
+                                  &cert_chain_list[i]);
+        // Strongbox may not support factory provisioned attestation key.
+        if (SecLevel() == SecurityLevel::STRONGBOX) {
+            if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+        }
+        ASSERT_EQ(ErrorCode::OK, result);
 
         AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
         AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
         ASSERT_GT(cert_chain_list[i].size(), 0);
-        EXPECT_TRUE(verify_attestation_record("foo", "bar", sw_enforced, hw_enforced, SecLevel(),
+        EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
+                                              SecLevel(),
                                               cert_chain_list[i][0].encodedCertificate));
 
         if (i > 0) {
@@ -412,6 +456,31 @@
 }
 
 /*
+ * AttestKeyTest.EcAttestKeyMultiPurposeFail
+ *
+ * This test attempts to create an EC attestation key that also allows signing.
+ */
+TEST_P(AttestKeyTest, EcAttestKeyMultiPurposeFail) {
+    if (AidlVersion() < 2) {
+        // The KeyMint v1 spec required that KeyPurpose::ATTEST_KEY not be combined
+        // with other key purposes.  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() << "Single-purpose for KeyPurpose::ATTEST_KEY only strict since KeyMint v2";
+    }
+    vector<uint8_t> attest_key_blob;
+    vector<KeyCharacteristics> attest_key_characteristics;
+    vector<Certificate> attest_key_cert_chain;
+    ASSERT_EQ(ErrorCode::INCOMPATIBLE_PURPOSE,
+              GenerateKey(AuthorizationSetBuilder()
+                                  .EcdsaSigningKey(EcCurve::P_256)
+                                  .AttestKey()
+                                  .SetDefaultValidity(),
+                          {} /* attestation signing key */, &attest_key_blob,
+                          &attest_key_characteristics, &attest_key_cert_chain));
+}
+
+/*
  * AttestKeyTest.AlternateAttestKeyChaining
  *
  * This test creates a chain of multiple attest keys, in the order Ec - RSA - Ec - RSA ....
@@ -442,39 +511,43 @@
             attest_key.keyBlob = key_blob_list[i - 1];
             attest_key_opt = attest_key;
         }
-
+        ErrorCode result;
         if ((i & 0x1) == 1) {
-            EXPECT_EQ(ErrorCode::OK,
-                      GenerateKey(AuthorizationSetBuilder()
-                                          .EcdsaKey(EcCurve::P_256)
-                                          .AttestKey()
-                                          .AttestationChallenge("foo")
-                                          .AttestationApplicationId("bar")
-                                          .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
-                                          .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
-                                          .Authorization(TAG_NO_AUTH_REQUIRED)
-                                          .SetDefaultValidity(),
-                                  attest_key_opt, &key_blob_list[i], &attested_key_characteristics,
-                                  &cert_chain_list[i]));
+            result = GenerateKey(AuthorizationSetBuilder()
+                                         .EcdsaKey(EcCurve::P_256)
+                                         .AttestKey()
+                                         .AttestationChallenge("foo")
+                                         .AttestationApplicationId("bar")
+                                         .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+                                         .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+                                         .Authorization(TAG_NO_AUTH_REQUIRED)
+                                         .SetDefaultValidity(),
+                                 attest_key_opt, &key_blob_list[i], &attested_key_characteristics,
+                                 &cert_chain_list[i]);
         } else {
-            EXPECT_EQ(ErrorCode::OK,
-                      GenerateKey(AuthorizationSetBuilder()
-                                          .RsaKey(2048, 65537)
-                                          .AttestKey()
-                                          .AttestationChallenge("foo")
-                                          .AttestationApplicationId("bar")
-                                          .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
-                                          .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
-                                          .Authorization(TAG_NO_AUTH_REQUIRED)
-                                          .SetDefaultValidity(),
-                                  attest_key_opt, &key_blob_list[i], &attested_key_characteristics,
-                                  &cert_chain_list[i]));
+            result = GenerateKey(AuthorizationSetBuilder()
+                                         .RsaKey(2048, 65537)
+                                         .AttestKey()
+                                         .AttestationChallenge("foo")
+                                         .AttestationApplicationId("bar")
+                                         .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+                                         .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+                                         .Authorization(TAG_NO_AUTH_REQUIRED)
+                                         .SetDefaultValidity(),
+                                 attest_key_opt, &key_blob_list[i], &attested_key_characteristics,
+                                 &cert_chain_list[i]);
         }
+        // Strongbox may not support factory provisioned attestation key.
+        if (SecLevel() == SecurityLevel::STRONGBOX) {
+            if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+        }
+        ASSERT_EQ(ErrorCode::OK, result);
 
         AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
         AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
         ASSERT_GT(cert_chain_list[i].size(), 0);
-        EXPECT_TRUE(verify_attestation_record("foo", "bar", sw_enforced, hw_enforced, SecLevel(),
+        EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
+                                              SecLevel(),
                                               cert_chain_list[i][0].encodedCertificate));
 
         if (i > 0) {
@@ -583,11 +656,13 @@
                               attest_key, &attested_key_blob, &attested_key_characteristics,
                               &attested_key_cert_chain));
 
+        ASSERT_GT(attested_key_cert_chain.size(), 0);
         CheckedDeleteKey(&attested_key_blob);
 
         AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
         AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
-        EXPECT_TRUE(verify_attestation_record("foo", "bar", sw_enforced, hw_enforced, SecLevel(),
+        EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
+                                              SecLevel(),
                                               attested_key_cert_chain[0].encodedCertificate));
 
         // Attestation by itself is not valid (last entry is not self-signed).
@@ -612,12 +687,14 @@
                               attest_key, &attested_key_blob, &attested_key_characteristics,
                               &attested_key_cert_chain));
 
+        ASSERT_GT(attested_key_cert_chain.size(), 0);
         CheckedDeleteKey(&attested_key_blob);
         CheckedDeleteKey(&attest_key.keyBlob);
 
         hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
         sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
-        EXPECT_TRUE(verify_attestation_record("foo", "bar", sw_enforced, hw_enforced, SecLevel(),
+        EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
+                                              SecLevel(),
                                               attested_key_cert_chain[0].encodedCertificate));
 
         // Attestation by itself is not valid (last entry is not self-signed).
@@ -666,6 +743,11 @@
 }
 
 TEST_P(AttestKeyTest, EcdsaAttestationID) {
+    if (is_gsi_image()) {
+        // GSI sets up a standard set of device identifiers that may not match
+        // the device identifiers held by the device.
+        GTEST_SKIP() << "Test not applicable under GSI";
+    }
     // Create attestation key.
     AttestationKey attest_key;
     vector<KeyCharacteristics> attest_key_characteristics;
@@ -706,7 +788,7 @@
         vector<Certificate> attested_key_cert_chain;
         auto result = GenerateKey(builder, attest_key, &attested_key_blob,
                                   &attested_key_characteristics, &attested_key_cert_chain);
-        if (result == ErrorCode::CANNOT_ATTEST_IDS) {
+        if (result == ErrorCode::CANNOT_ATTEST_IDS && !isDeviceIdAttestationRequired()) {
             continue;
         }
 
@@ -722,8 +804,8 @@
         // attestation extension should contain them, so make sure the extra tag is added.
         hw_enforced.push_back(tag);
 
-        EXPECT_TRUE(verify_attestation_record("challenge", "foo", sw_enforced, hw_enforced,
-                                              SecLevel(),
+        EXPECT_TRUE(verify_attestation_record(AidlVersion(), "challenge", "foo", sw_enforced,
+                                              hw_enforced, SecLevel(),
                                               attested_key_cert_chain[0].encodedCertificate));
     }
     CheckedDeleteKey(&attest_key.keyBlob);
diff --git a/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp b/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
index 79716b1..1dc5df3 100644
--- a/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
+++ b/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
@@ -52,8 +52,9 @@
         EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_, /* strict_issuer_check= */ false));
 
         AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
-        EXPECT_TRUE(verify_attestation_record("challenge", "foo", sw_enforced, hw_enforced,
-                                              SecLevel(), cert_chain_[0].encodedCertificate));
+        EXPECT_TRUE(verify_attestation_record(AidlVersion(), "challenge", "foo", sw_enforced,
+                                              hw_enforced, SecLevel(),
+                                              cert_chain_[0].encodedCertificate));
     }
 };
 
@@ -64,7 +65,9 @@
  * attestation.
  */
 TEST_P(DeviceUniqueAttestationTest, RsaNonStrongBoxUnimplemented) {
-    if (SecLevel() == SecurityLevel::STRONGBOX) return;
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        GTEST_SKIP() << "Test not applicable to StrongBox device";
+    }
 
     vector<uint8_t> key_blob;
     vector<KeyCharacteristics> key_characteristics;
@@ -77,6 +80,7 @@
                                       .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)
                                       .Authorization(TAG_INCLUDE_UNIQUE_ID)
                                       .Authorization(TAG_CREATION_DATETIME, 1619621648000)
+                                      .SetDefaultValidity()
                                       .AttestationChallenge("challenge")
                                       .AttestationApplicationId("foo")
                                       .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION),
@@ -92,7 +96,9 @@
  * attestation.
  */
 TEST_P(DeviceUniqueAttestationTest, EcdsaNonStrongBoxUnimplemented) {
-    if (SecLevel() == SecurityLevel::STRONGBOX) return;
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        GTEST_SKIP() << "Test not applicable to StrongBox device";
+    }
 
     vector<uint8_t> key_blob;
     vector<KeyCharacteristics> key_characteristics;
@@ -104,6 +110,7 @@
                                       .Digest(Digest::SHA_2_256)
                                       .Authorization(TAG_INCLUDE_UNIQUE_ID)
                                       .Authorization(TAG_CREATION_DATETIME, 1619621648000)
+                                      .SetDefaultValidity()
                                       .AttestationChallenge("challenge")
                                       .AttestationApplicationId("foo")
                                       .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION),
@@ -119,7 +126,9 @@
  * attestation correctly, if implemented.
  */
 TEST_P(DeviceUniqueAttestationTest, RsaDeviceUniqueAttestation) {
-    if (SecLevel() != SecurityLevel::STRONGBOX) return;
+    if (SecLevel() != SecurityLevel::STRONGBOX) {
+        GTEST_SKIP() << "Test not applicable to non-StrongBox device";
+    }
 
     vector<uint8_t> key_blob;
     vector<KeyCharacteristics> key_characteristics;
@@ -132,6 +141,7 @@
                                       .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)
                                       .Authorization(TAG_INCLUDE_UNIQUE_ID)
                                       .Authorization(TAG_CREATION_DATETIME, 1619621648000)
+                                      .SetDefaultValidity()
                                       .AttestationChallenge("challenge")
                                       .AttestationApplicationId("foo")
                                       .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION),
@@ -177,7 +187,9 @@
  * attestation correctly, if implemented.
  */
 TEST_P(DeviceUniqueAttestationTest, EcdsaDeviceUniqueAttestation) {
-    if (SecLevel() != SecurityLevel::STRONGBOX) return;
+    if (SecLevel() != SecurityLevel::STRONGBOX) {
+        GTEST_SKIP() << "Test not applicable to non-StrongBox device";
+    }
 
     vector<uint8_t> key_blob;
     vector<KeyCharacteristics> key_characteristics;
@@ -188,6 +200,7 @@
                                       .Digest(Digest::SHA_2_256)
                                       .Authorization(TAG_INCLUDE_UNIQUE_ID)
                                       .Authorization(TAG_CREATION_DATETIME, 1619621648000)
+                                      .SetDefaultValidity()
                                       .AttestationChallenge("challenge")
                                       .AttestationApplicationId("foo")
                                       .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION),
@@ -230,7 +243,9 @@
  * local device.
  */
 TEST_P(DeviceUniqueAttestationTest, EcdsaDeviceUniqueAttestationID) {
-    if (SecLevel() != SecurityLevel::STRONGBOX) return;
+    if (SecLevel() != SecurityLevel::STRONGBOX) {
+        GTEST_SKIP() << "Test not applicable to non-StrongBox device";
+    }
 
     // Collection of valid attestation ID tags.
     auto attestation_id_tags = AuthorizationSetBuilder();
@@ -253,6 +268,7 @@
                         .Digest(Digest::SHA_2_256)
                         .Authorization(TAG_INCLUDE_UNIQUE_ID)
                         .Authorization(TAG_CREATION_DATETIME, 1619621648000)
+                        .SetDefaultValidity()
                         .AttestationChallenge("challenge")
                         .AttestationApplicationId("foo")
                         .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION);
@@ -298,7 +314,9 @@
  * don't match the local device.
  */
 TEST_P(DeviceUniqueAttestationTest, EcdsaDeviceUniqueAttestationMismatchID) {
-    if (SecLevel() != SecurityLevel::STRONGBOX) return;
+    if (SecLevel() != SecurityLevel::STRONGBOX) {
+        GTEST_SKIP() << "Test not applicable to non-StrongBox device";
+    }
 
     // Collection of invalid attestation ID tags.
     auto attestation_id_tags =
@@ -323,6 +341,7 @@
                         .Digest(Digest::SHA_2_256)
                         .Authorization(TAG_INCLUDE_UNIQUE_ID)
                         .Authorization(TAG_CREATION_DATETIME, 1619621648000)
+                        .SetDefaultValidity()
                         .AttestationChallenge("challenge")
                         .AttestationApplicationId("foo")
                         .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION);
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 8e35c91..33945fd 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -17,6 +17,7 @@
 #include "KeyMintAidlTestBase.h"
 
 #include <chrono>
+#include <fstream>
 #include <unordered_set>
 #include <vector>
 
@@ -25,11 +26,11 @@
 #include <cppbor_parse.h>
 #include <cutils/properties.h>
 #include <gmock/gmock.h>
+#include <openssl/evp.h>
 #include <openssl/mem.h>
 #include <remote_prov/remote_prov_utils.h>
 
 #include <keymaster/cppcose/cppcose.h>
-#include <keymint_support/attestation_record.h>
 #include <keymint_support/key_param_output.h>
 #include <keymint_support/keymint_utils.h>
 #include <keymint_support/openssl_utils.h>
@@ -77,12 +78,18 @@
 
     std::unordered_set<SecurityLevel> levels_seen;
     for (auto& entry : key_characteristics) {
-        if (entry.authorizations.empty()) return false;
+        if (entry.authorizations.empty()) {
+            GTEST_LOG_(ERROR) << "empty authorizations for " << entry.securityLevel;
+            return false;
+        }
 
         // Just ignore the SecurityLevel::KEYSTORE as the KM won't do any enforcement on this.
         if (entry.securityLevel == SecurityLevel::KEYSTORE) continue;
 
-        if (levels_seen.find(entry.securityLevel) != levels_seen.end()) return false;
+        if (levels_seen.find(entry.securityLevel) != levels_seen.end()) {
+            GTEST_LOG_(ERROR) << "duplicate authorizations for " << entry.securityLevel;
+            return false;
+        }
         levels_seen.insert(entry.securityLevel);
 
         // Generally, we should only have one entry, at the same security level as the KM
@@ -92,7 +99,10 @@
                                        (secLevel == SecurityLevel::STRONGBOX &&
                                         entry.securityLevel == SecurityLevel::TRUSTED_ENVIRONMENT);
 
-        if (!isExpectedSecurityLevel) return false;
+        if (!isExpectedSecurityLevel) {
+            GTEST_LOG_(ERROR) << "Unexpected security level " << entry.securityLevel;
+            return false;
+        }
     }
     return true;
 }
@@ -118,6 +128,16 @@
     return attest_rec;
 }
 
+void check_attestation_version(uint32_t attestation_version, int32_t aidl_version) {
+    // Version numbers in attestation extensions should be a multiple of 100.
+    EXPECT_EQ(attestation_version % 100, 0);
+
+    // The multiplier should never be higher than the AIDL version, but can be less
+    // (for example, if the implementation is from an earlier version but the HAL service
+    // uses the default libraries and so reports the current AIDL version).
+    EXPECT_TRUE((attestation_version / 100) <= aidl_version);
+}
+
 bool avb_verification_enabled() {
     char value[PROPERTY_VALUE_MAX];
     return property_get("ro.boot.vbmeta.device_state", value, "") != 0;
@@ -187,6 +207,29 @@
     return boot_patch_level(key_characteristics_);
 }
 
+/**
+ * An API to determine device IDs attestation is required or not,
+ * which is mandatory for KeyMint version 2 or first_api_level 33 or greater.
+ */
+bool KeyMintAidlTestBase::isDeviceIdAttestationRequired() {
+    return AidlVersion() >= 2 || property_get_int32("ro.vendor.api_level", 0) >= 33;
+}
+
+bool KeyMintAidlTestBase::Curve25519Supported() {
+    // Strongbox never supports curve 25519.
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        return false;
+    }
+
+    // Curve 25519 was included in version 2 of the KeyMint interface.
+    int32_t version = 0;
+    auto status = keymint_->getInterfaceVersion(&version);
+    if (!status.isOk()) {
+        ADD_FAILURE() << "Failed to determine interface version";
+    }
+    return version >= 2;
+}
+
 ErrorCode KeyMintAidlTestBase::GetReturnErrorCode(const Status& result) {
     if (result.isOk()) return ErrorCode::OK;
 
@@ -214,6 +257,15 @@
     vendor_patch_level_ = getVendorPatchlevel();
 }
 
+int32_t KeyMintAidlTestBase::AidlVersion() {
+    int32_t version = 0;
+    auto status = keymint_->getInterfaceVersion(&version);
+    if (!status.isOk()) {
+        ADD_FAILURE() << "Failed to determine interface version";
+    }
+    return version;
+}
+
 void KeyMintAidlTestBase::SetUp() {
     if (AServiceManager_isDeclared(GetParam().c_str())) {
         ::ndk::SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str()));
@@ -268,6 +320,30 @@
     return GenerateKey(key_desc, attest_key, &key_blob_, &key_characteristics_, &cert_chain_);
 }
 
+ErrorCode KeyMintAidlTestBase::GenerateKeyWithSelfSignedAttestKey(
+        const AuthorizationSet& attest_key_desc, const AuthorizationSet& key_desc,
+        vector<uint8_t>* key_blob, vector<KeyCharacteristics>* key_characteristics,
+        vector<Certificate>* cert_chain) {
+    AttestationKey attest_key;
+    vector<Certificate> attest_cert_chain;
+    vector<KeyCharacteristics> attest_key_characteristics;
+    // Generate a key with self signed attestation.
+    auto error = GenerateKey(attest_key_desc, std::nullopt, &attest_key.keyBlob,
+                             &attest_key_characteristics, &attest_cert_chain);
+    if (error != ErrorCode::OK) {
+        return error;
+    }
+
+    attest_key.issuerSubjectName = make_name_from_str("Android Keystore Key");
+    // Generate a key, by passing the above self signed attestation key as attest key.
+    error = GenerateKey(key_desc, attest_key, key_blob, key_characteristics, cert_chain);
+    if (error == ErrorCode::OK) {
+        // Append the attest_cert_chain to the attested cert_chain to yield a valid cert chain.
+        cert_chain->push_back(attest_cert_chain[0]);
+    }
+    return error;
+}
+
 ErrorCode KeyMintAidlTestBase::ImportKey(const AuthorizationSet& key_desc, KeyFormat format,
                                          const string& key_material, vector<uint8_t>* key_blob,
                                          vector<KeyCharacteristics>* key_characteristics) {
@@ -509,10 +585,18 @@
     Status result;
     if (!output) return ErrorCode::UNEXPECTED_NULL_POINTER;
 
+    EXPECT_NE(op_, nullptr);
+    if (!op_) return ErrorCode::UNEXPECTED_NULL_POINTER;
+
     std::vector<uint8_t> o_put;
     result = op_->update(vector<uint8_t>(input.begin(), input.end()), {}, {}, &o_put);
 
-    if (result.isOk()) output->append(o_put.begin(), o_put.end());
+    if (result.isOk()) {
+        output->append(o_put.begin(), o_put.end());
+    } else {
+        // Failure always terminates the operation.
+        op_ = {};
+    }
 
     return GetReturnErrorCode(result);
 }
@@ -613,6 +697,81 @@
             AuthorizationSetBuilder().Digest(digest).Authorization(TAG_MAC_LENGTH, mac_length));
 }
 
+void KeyMintAidlTestBase::CheckAesIncrementalEncryptOperation(BlockMode block_mode,
+                                                              int message_size) {
+    auto builder = AuthorizationSetBuilder()
+                           .Authorization(TAG_NO_AUTH_REQUIRED)
+                           .AesEncryptionKey(128)
+                           .BlockMode(block_mode)
+                           .Padding(PaddingMode::NONE);
+    if (block_mode == BlockMode::GCM) {
+        builder.Authorization(TAG_MIN_MAC_LENGTH, 128);
+    }
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(builder));
+
+    for (int increment = 1; increment <= message_size; ++increment) {
+        string message(message_size, 'a');
+        auto params = AuthorizationSetBuilder().BlockMode(block_mode).Padding(PaddingMode::NONE);
+        if (block_mode == BlockMode::GCM) {
+            params.Authorization(TAG_MAC_LENGTH, 128) /* for GCM */;
+        }
+
+        AuthorizationSet output_params;
+        EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params, &output_params));
+
+        string ciphertext;
+        string to_send;
+        for (size_t i = 0; i < message.size(); i += increment) {
+            EXPECT_EQ(ErrorCode::OK, Update(message.substr(i, increment), &ciphertext));
+        }
+        EXPECT_EQ(ErrorCode::OK, Finish(to_send, &ciphertext))
+                << "Error sending " << to_send << " with block mode " << block_mode;
+
+        switch (block_mode) {
+            case BlockMode::GCM:
+                EXPECT_EQ(message.size() + 16, ciphertext.size());
+                break;
+            case BlockMode::CTR:
+                EXPECT_EQ(message.size(), ciphertext.size());
+                break;
+            case BlockMode::CBC:
+            case BlockMode::ECB:
+                EXPECT_EQ(message.size() + message.size() % 16, ciphertext.size());
+                break;
+        }
+
+        auto iv = output_params.GetTagValue(TAG_NONCE);
+        switch (block_mode) {
+            case BlockMode::CBC:
+            case BlockMode::GCM:
+            case BlockMode::CTR:
+                ASSERT_TRUE(iv) << "No IV for block mode " << block_mode;
+                EXPECT_EQ(block_mode == BlockMode::GCM ? 12U : 16U, iv->get().size());
+                params.push_back(TAG_NONCE, iv->get());
+                break;
+
+            case BlockMode::ECB:
+                EXPECT_FALSE(iv) << "ECB mode should not generate IV";
+                break;
+        }
+
+        EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params))
+                << "Decrypt begin() failed for block mode " << block_mode;
+
+        string plaintext;
+        for (size_t i = 0; i < ciphertext.size(); i += increment) {
+            EXPECT_EQ(ErrorCode::OK, Update(ciphertext.substr(i, increment), &plaintext));
+        }
+        ErrorCode error = Finish(to_send, &plaintext);
+        ASSERT_EQ(ErrorCode::OK, error) << "Decryption failed for block mode " << block_mode
+                                        << " and increment " << increment;
+        if (error == ErrorCode::OK) {
+            ASSERT_EQ(message, plaintext) << "Decryption didn't match for block mode " << block_mode
+                                          << " and increment " << increment;
+        }
+    }
+}
+
 void KeyMintAidlTestBase::CheckHmacTestVector(const string& key, const string& message,
                                               Digest digest, const string& expected_mac) {
     SCOPED_TRACE("CheckHmacTestVector");
@@ -709,6 +868,19 @@
 
     if (digest == Digest::NONE) {
         switch (EVP_PKEY_id(pub_key.get())) {
+            case EVP_PKEY_ED25519: {
+                ASSERT_EQ(64, signature.size());
+                uint8_t pub_keydata[32];
+                size_t pub_len = sizeof(pub_keydata);
+                ASSERT_EQ(1, EVP_PKEY_get_raw_public_key(pub_key.get(), pub_keydata, &pub_len));
+                ASSERT_EQ(sizeof(pub_keydata), pub_len);
+                ASSERT_EQ(1, ED25519_verify(reinterpret_cast<const uint8_t*>(message.data()),
+                                            message.size(),
+                                            reinterpret_cast<const uint8_t*>(signature.data()),
+                                            pub_keydata));
+                break;
+            }
+
             case EVP_PKEY_EC: {
                 vector<uint8_t> data((EVP_PKEY_bits(pub_key.get()) + 7) / 8);
                 size_t data_size = std::min(data.size(), message.size());
@@ -781,6 +953,7 @@
         if (padding == PaddingMode::RSA_PSS) {
             EXPECT_GT(EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING), 0);
             EXPECT_GT(EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, EVP_MD_size(md)), 0);
+            EXPECT_GT(EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, md), 0);
         }
 
         ASSERT_EQ(1, EVP_DigestVerifyUpdate(&digest_ctx,
@@ -1058,6 +1231,8 @@
         }
     } else {
         switch (algorithm) {
+            case Algorithm::AES:
+                return {64, 96, 131, 512};
             case Algorithm::TRIPLE_DES:
                 return {56};
             default:
@@ -1132,16 +1307,39 @@
 vector<EcCurve> KeyMintAidlTestBase::ValidCurves() {
     if (securityLevel_ == SecurityLevel::STRONGBOX) {
         return {EcCurve::P_256};
+    } else if (Curve25519Supported()) {
+        return {EcCurve::P_224, EcCurve::P_256, EcCurve::P_384, EcCurve::P_521,
+                EcCurve::CURVE_25519};
     } else {
-        return {EcCurve::P_224, EcCurve::P_256, EcCurve::P_384, EcCurve::P_521};
+        return {
+                EcCurve::P_224,
+                EcCurve::P_256,
+                EcCurve::P_384,
+                EcCurve::P_521,
+        };
     }
 }
 
 vector<EcCurve> KeyMintAidlTestBase::InvalidCurves() {
     if (SecLevel() == SecurityLevel::STRONGBOX) {
-        return {EcCurve::P_224, EcCurve::P_384, EcCurve::P_521};
+        // Curve 25519 is not supported, either because:
+        // - KeyMint v1: it's an unknown enum value
+        // - KeyMint v2+: it's not supported by StrongBox.
+        return {EcCurve::P_224, EcCurve::P_384, EcCurve::P_521, EcCurve::CURVE_25519};
     } else {
-        return {};
+        if (Curve25519Supported()) {
+            return {};
+        } else {
+            return {EcCurve::CURVE_25519};
+        }
+    }
+}
+
+vector<uint64_t> KeyMintAidlTestBase::ValidExponents() {
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        return {65537};
+    } else {
+        return {3, 65537};
     }
 }
 
@@ -1262,6 +1460,33 @@
     OPENSSL_free(cert_issuer);
 }
 
+int get_vsr_api_level() {
+    int api_level = ::android::base::GetIntProperty("ro.board.api_level", -1);
+    if (api_level == -1) {
+        api_level = ::android::base::GetIntProperty("ro.board.first_api_level", -1);
+    }
+    if (api_level == -1) {
+        api_level = ::android::base::GetIntProperty("ro.vndk.version", -1);
+    }
+    // We really should have a VSR API level by now.  But on cuttlefish, and perhaps other weird
+    // devices, we may not.  So, we use the SDK first or current API level if needed.  If this goes
+    // wrong, it should go wrong in the direction of being too strict rather than too lenient, which
+    // should provoke someone to examine why we don't have proper VSR API level properties.
+    if (api_level == -1) {
+        api_level = ::android::base::GetIntProperty("ro.product.first_api_level", -1);
+    }
+    if (api_level == -1) {
+        api_level = ::android::base::GetIntProperty("ro.build.version.sdk", -1);
+    }
+    EXPECT_NE(api_level, -1) << "Could not find a VSR level, or equivalent.";
+    return api_level;
+}
+
+bool is_gsi_image() {
+    std::ifstream ifs("/system/system_ext/etc/init/init.gsi.rc");
+    return ifs.good();
+}
+
 vector<uint8_t> build_serial_blob(const uint64_t serial_int) {
     BIGNUM_Ptr serial(BN_new());
     EXPECT_TRUE(BN_set_u64(serial.get(), serial_int));
@@ -1293,115 +1518,10 @@
     verify_subject(cert.get(), subject, self_signed);
 }
 
-bool verify_attestation_record(const string& challenge,                //
-                               const string& app_id,                   //
-                               AuthorizationSet expected_sw_enforced,  //
-                               AuthorizationSet expected_hw_enforced,  //
-                               SecurityLevel security_level,
-                               const vector<uint8_t>& attestation_cert,
-                               vector<uint8_t>* unique_id) {
-    X509_Ptr cert(parse_cert_blob(attestation_cert));
-    EXPECT_TRUE(!!cert.get());
-    if (!cert.get()) return false;
-
-    ASN1_OCTET_STRING* attest_rec = get_attestation_record(cert.get());
-    EXPECT_TRUE(!!attest_rec);
-    if (!attest_rec) return false;
-
-    AuthorizationSet att_sw_enforced;
-    AuthorizationSet att_hw_enforced;
-    uint32_t att_attestation_version;
-    uint32_t att_keymint_version;
-    SecurityLevel att_attestation_security_level;
-    SecurityLevel att_keymint_security_level;
-    vector<uint8_t> att_challenge;
-    vector<uint8_t> att_unique_id;
-    vector<uint8_t> att_app_id;
-
-    auto error = parse_attestation_record(attest_rec->data,                 //
-                                          attest_rec->length,               //
-                                          &att_attestation_version,         //
-                                          &att_attestation_security_level,  //
-                                          &att_keymint_version,             //
-                                          &att_keymint_security_level,      //
-                                          &att_challenge,                   //
-                                          &att_sw_enforced,                 //
-                                          &att_hw_enforced,                 //
-                                          &att_unique_id);
-    EXPECT_EQ(ErrorCode::OK, error);
-    if (error != ErrorCode::OK) return false;
-
-    EXPECT_EQ(att_attestation_version, 100U);
-    vector<uint8_t> appId(app_id.begin(), app_id.end());
-
-    // check challenge and app id only if we expects a non-fake certificate
-    if (challenge.length() > 0) {
-        EXPECT_EQ(challenge.length(), att_challenge.size());
-        EXPECT_EQ(0, memcmp(challenge.data(), att_challenge.data(), challenge.length()));
-
-        expected_sw_enforced.push_back(TAG_ATTESTATION_APPLICATION_ID, appId);
-    }
-
-    EXPECT_EQ(att_keymint_version, 100U);
-    EXPECT_EQ(security_level, att_keymint_security_level);
-    EXPECT_EQ(security_level, att_attestation_security_level);
-
-
+void verify_root_of_trust(const vector<uint8_t>& verified_boot_key, bool device_locked,
+                          VerifiedBoot verified_boot_state,
+                          const vector<uint8_t>& verified_boot_hash) {
     char property_value[PROPERTY_VALUE_MAX] = {};
-    // TODO(b/136282179): When running under VTS-on-GSI the TEE-backed
-    // keymint implementation will report YYYYMM dates instead of YYYYMMDD
-    // for the BOOT_PATCH_LEVEL.
-    if (avb_verification_enabled()) {
-        for (int i = 0; i < att_hw_enforced.size(); i++) {
-            if (att_hw_enforced[i].tag == TAG_BOOT_PATCHLEVEL ||
-                att_hw_enforced[i].tag == TAG_VENDOR_PATCHLEVEL) {
-                std::string date =
-                        std::to_string(att_hw_enforced[i].value.get<KeyParameterValue::integer>());
-                // strptime seems to require delimiters, but the tag value will
-                // be YYYYMMDD
-                date.insert(6, "-");
-                date.insert(4, "-");
-                EXPECT_EQ(date.size(), 10);
-                struct tm time;
-                strptime(date.c_str(), "%Y-%m-%d", &time);
-
-                // Day of the month (0-31)
-                EXPECT_GE(time.tm_mday, 0);
-                EXPECT_LT(time.tm_mday, 32);
-                // Months since Jan (0-11)
-                EXPECT_GE(time.tm_mon, 0);
-                EXPECT_LT(time.tm_mon, 12);
-                // Years since 1900
-                EXPECT_GT(time.tm_year, 110);
-                EXPECT_LT(time.tm_year, 200);
-            }
-        }
-    }
-
-    // Check to make sure boolean values are properly encoded. Presence of a boolean tag
-    // indicates true. A provided boolean tag that can be pulled back out of the certificate
-    // indicates correct encoding. No need to check if it's in both lists, since the
-    // AuthorizationSet compare below will handle mismatches of tags.
-    if (security_level == SecurityLevel::SOFTWARE) {
-        EXPECT_TRUE(expected_sw_enforced.Contains(TAG_NO_AUTH_REQUIRED));
-    } else {
-        EXPECT_TRUE(expected_hw_enforced.Contains(TAG_NO_AUTH_REQUIRED));
-    }
-
-    if (att_hw_enforced.Contains(TAG_ALGORITHM, Algorithm::EC)) {
-        // For ECDSA keys, either an EC_CURVE or a KEY_SIZE can be specified, but one must be.
-        EXPECT_TRUE(att_hw_enforced.Contains(TAG_EC_CURVE) ||
-                    att_hw_enforced.Contains(TAG_KEY_SIZE));
-    }
-
-    // Test root of trust elements
-    vector<uint8_t> verified_boot_key;
-    VerifiedBoot verified_boot_state;
-    bool device_locked;
-    vector<uint8_t> verified_boot_hash;
-    error = parse_root_of_trust(attest_rec->data, attest_rec->length, &verified_boot_key,
-                                &verified_boot_state, &device_locked, &verified_boot_hash);
-    EXPECT_EQ(ErrorCode::OK, error);
 
     if (avb_verification_enabled()) {
         EXPECT_NE(property_get("ro.boot.vbmeta.digest", property_value, ""), 0);
@@ -1447,9 +1567,125 @@
         EXPECT_EQ(verified_boot_state, VerifiedBoot::FAILED);
     } else {
         EXPECT_EQ(verified_boot_state, VerifiedBoot::UNVERIFIED);
-        EXPECT_NE(0, memcmp(verified_boot_key.data(), empty_boot_key.data(),
+        EXPECT_EQ(0, memcmp(verified_boot_key.data(), empty_boot_key.data(),
                             verified_boot_key.size()));
     }
+}
+
+bool verify_attestation_record(int32_t aidl_version,                   //
+                               const string& challenge,                //
+                               const string& app_id,                   //
+                               AuthorizationSet expected_sw_enforced,  //
+                               AuthorizationSet expected_hw_enforced,  //
+                               SecurityLevel security_level,
+                               const vector<uint8_t>& attestation_cert,
+                               vector<uint8_t>* unique_id) {
+    X509_Ptr cert(parse_cert_blob(attestation_cert));
+    EXPECT_TRUE(!!cert.get());
+    if (!cert.get()) return false;
+
+    ASN1_OCTET_STRING* attest_rec = get_attestation_record(cert.get());
+    EXPECT_TRUE(!!attest_rec);
+    if (!attest_rec) return false;
+
+    AuthorizationSet att_sw_enforced;
+    AuthorizationSet att_hw_enforced;
+    uint32_t att_attestation_version;
+    uint32_t att_keymint_version;
+    SecurityLevel att_attestation_security_level;
+    SecurityLevel att_keymint_security_level;
+    vector<uint8_t> att_challenge;
+    vector<uint8_t> att_unique_id;
+    vector<uint8_t> att_app_id;
+
+    auto error = parse_attestation_record(attest_rec->data,                 //
+                                          attest_rec->length,               //
+                                          &att_attestation_version,         //
+                                          &att_attestation_security_level,  //
+                                          &att_keymint_version,             //
+                                          &att_keymint_security_level,      //
+                                          &att_challenge,                   //
+                                          &att_sw_enforced,                 //
+                                          &att_hw_enforced,                 //
+                                          &att_unique_id);
+    EXPECT_EQ(ErrorCode::OK, error);
+    if (error != ErrorCode::OK) return false;
+
+    check_attestation_version(att_attestation_version, aidl_version);
+    vector<uint8_t> appId(app_id.begin(), app_id.end());
+
+    // check challenge and app id only if we expects a non-fake certificate
+    if (challenge.length() > 0) {
+        EXPECT_EQ(challenge.length(), att_challenge.size());
+        EXPECT_EQ(0, memcmp(challenge.data(), att_challenge.data(), challenge.length()));
+
+        expected_sw_enforced.push_back(TAG_ATTESTATION_APPLICATION_ID, appId);
+    }
+
+    check_attestation_version(att_keymint_version, aidl_version);
+    EXPECT_EQ(security_level, att_keymint_security_level);
+    EXPECT_EQ(security_level, att_attestation_security_level);
+
+    // TODO(b/136282179): When running under VTS-on-GSI the TEE-backed
+    // keymint implementation will report YYYYMM dates instead of YYYYMMDD
+    // for the BOOT_PATCH_LEVEL.
+    if (avb_verification_enabled()) {
+        for (int i = 0; i < att_hw_enforced.size(); i++) {
+            if (att_hw_enforced[i].tag == TAG_BOOT_PATCHLEVEL ||
+                att_hw_enforced[i].tag == TAG_VENDOR_PATCHLEVEL) {
+                std::string date =
+                        std::to_string(att_hw_enforced[i].value.get<KeyParameterValue::integer>());
+
+                // strptime seems to require delimiters, but the tag value will
+                // be YYYYMMDD
+                if (date.size() != 8) {
+                    ADD_FAILURE() << "Tag " << att_hw_enforced[i].tag
+                                  << " with invalid format (not YYYYMMDD): " << date;
+                    return false;
+                }
+                date.insert(6, "-");
+                date.insert(4, "-");
+                struct tm time;
+                strptime(date.c_str(), "%Y-%m-%d", &time);
+
+                // Day of the month (0-31)
+                EXPECT_GE(time.tm_mday, 0);
+                EXPECT_LT(time.tm_mday, 32);
+                // Months since Jan (0-11)
+                EXPECT_GE(time.tm_mon, 0);
+                EXPECT_LT(time.tm_mon, 12);
+                // Years since 1900
+                EXPECT_GT(time.tm_year, 110);
+                EXPECT_LT(time.tm_year, 200);
+            }
+        }
+    }
+
+    // Check to make sure boolean values are properly encoded. Presence of a boolean tag
+    // indicates true. A provided boolean tag that can be pulled back out of the certificate
+    // indicates correct encoding. No need to check if it's in both lists, since the
+    // AuthorizationSet compare below will handle mismatches of tags.
+    if (security_level == SecurityLevel::SOFTWARE) {
+        EXPECT_TRUE(expected_sw_enforced.Contains(TAG_NO_AUTH_REQUIRED));
+    } else {
+        EXPECT_TRUE(expected_hw_enforced.Contains(TAG_NO_AUTH_REQUIRED));
+    }
+
+    if (att_hw_enforced.Contains(TAG_ALGORITHM, Algorithm::EC)) {
+        // For ECDSA keys, either an EC_CURVE or a KEY_SIZE can be specified, but one must be.
+        EXPECT_TRUE(att_hw_enforced.Contains(TAG_EC_CURVE) ||
+                    att_hw_enforced.Contains(TAG_KEY_SIZE));
+    }
+
+    // Test root of trust elements
+    vector<uint8_t> verified_boot_key;
+    VerifiedBoot verified_boot_state;
+    bool device_locked;
+    vector<uint8_t> verified_boot_hash;
+    error = parse_root_of_trust(attest_rec->data, attest_rec->length, &verified_boot_key,
+                                &verified_boot_state, &device_locked, &verified_boot_hash);
+    EXPECT_EQ(ErrorCode::OK, error);
+    verify_root_of_trust(verified_boot_key, device_locked, verified_boot_state, verified_boot_hash);
 
     att_sw_enforced.Sort();
     expected_sw_enforced.Sort();
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
index 7b3b9d4..8f9df24 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
@@ -31,6 +31,7 @@
 #include <aidl/android/hardware/security/keymint/IKeyMintDevice.h>
 #include <aidl/android/hardware/security/keymint/MacedPublicKey.h>
 
+#include <keymint_support/attestation_record.h>
 #include <keymint_support/authorization_set.h>
 #include <keymint_support/openssl_utils.h>
 
@@ -73,11 +74,15 @@
 
     void InitializeKeyMint(std::shared_ptr<IKeyMintDevice> keyMint);
     IKeyMintDevice& keyMint() { return *keymint_; }
+    int32_t AidlVersion();
     uint32_t os_version() { return os_version_; }
     uint32_t os_patch_level() { return os_patch_level_; }
     uint32_t vendor_patch_level() { return vendor_patch_level_; }
     uint32_t boot_patch_level(const vector<KeyCharacteristics>& key_characteristics);
     uint32_t boot_patch_level();
+    bool isDeviceIdAttestationRequired();
+
+    bool Curve25519Supported();
 
     ErrorCode GetReturnErrorCode(const Status& result);
 
@@ -93,6 +98,21 @@
     ErrorCode GenerateKey(const AuthorizationSet& key_desc,
                           const optional<AttestationKey>& attest_key = std::nullopt);
 
+    // Generate key for implementations which do not support factory attestation.
+    ErrorCode GenerateKeyWithSelfSignedAttestKey(const AuthorizationSet& attest_key_desc,
+                                                 const AuthorizationSet& key_desc,
+                                                 vector<uint8_t>* key_blob,
+                                                 vector<KeyCharacteristics>* key_characteristics,
+                                                 vector<Certificate>* cert_chain);
+
+    ErrorCode GenerateKeyWithSelfSignedAttestKey(const AuthorizationSet& attest_key_desc,
+                                                 const AuthorizationSet& key_desc,
+                                                 vector<uint8_t>* key_blob,
+                                                 vector<KeyCharacteristics>* key_characteristics) {
+        return GenerateKeyWithSelfSignedAttestKey(attest_key_desc, key_desc, key_blob,
+                                                  key_characteristics, &cert_chain_);
+    }
+
     ErrorCode ImportKey(const AuthorizationSet& key_desc, KeyFormat format,
                         const string& key_material, vector<uint8_t>* key_blob,
                         vector<KeyCharacteristics>* key_characteristics);
@@ -166,6 +186,8 @@
 
     string MacMessage(const string& message, Digest digest, size_t mac_length);
 
+    void CheckAesIncrementalEncryptOperation(BlockMode block_mode, int message_size);
+
     void CheckHmacTestVector(const string& key, const string& message, Digest digest,
                              const string& expected_mac);
 
@@ -250,7 +272,10 @@
                                                      .SetDefaultValidity();
         tagModifier(&rsaBuilder);
         errorCode = GenerateKey(rsaBuilder, &rsaKeyData.blob, &rsaKeyData.characteristics);
-        EXPECT_EQ(expectedReturn, errorCode);
+        if (!(SecLevel() == SecurityLevel::STRONGBOX &&
+              ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED == errorCode)) {
+            EXPECT_EQ(expectedReturn, errorCode);
+        }
 
         /* ECDSA */
         KeyData ecdsaKeyData;
@@ -262,7 +287,10 @@
                                                        .SetDefaultValidity();
         tagModifier(&ecdsaBuilder);
         errorCode = GenerateKey(ecdsaBuilder, &ecdsaKeyData.blob, &ecdsaKeyData.characteristics);
-        EXPECT_EQ(expectedReturn, errorCode);
+        if (!(SecLevel() == SecurityLevel::STRONGBOX &&
+              ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED == errorCode)) {
+            EXPECT_EQ(expectedReturn, errorCode);
+        }
         return {aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData};
     }
     bool IsSecure() const { return securityLevel_ != SecurityLevel::SOFTWARE; }
@@ -279,6 +307,7 @@
     vector<EcCurve> InvalidCurves();
 
     vector<Digest> ValidDigests(bool withNone, bool withMD5);
+    vector<uint64_t> ValidExponents();
 
     static vector<string> build_params() {
         auto params = ::android::getAidlHalInstanceNames(IKeyMintDevice::descriptor);
@@ -326,14 +355,24 @@
     }
 }
 
+// Return the VSR API level for this device.
+int get_vsr_api_level();
+
+// Indicate whether the test is running on a GSI image.
+bool is_gsi_image();
+
 vector<uint8_t> build_serial_blob(const uint64_t serial_int);
 void verify_subject(const X509* cert, const string& subject, bool self_signed);
 void verify_serial(X509* cert, const uint64_t expected_serial);
 void verify_subject_and_serial(const Certificate& certificate,  //
                                const uint64_t expected_serial,  //
                                const string& subject, bool self_signed);
-
-bool verify_attestation_record(const string& challenge,                //
+void verify_root_of_trust(const vector<uint8_t>& verified_boot_key,  //
+                          bool device_locked,                        //
+                          VerifiedBoot verified_boot_state,          //
+                          const vector<uint8_t>& verified_boot_hash);
+bool verify_attestation_record(int aidl_version,                       //
+                               const string& challenge,                //
                                const string& app_id,                   //
                                AuthorizationSet expected_sw_enforced,  //
                                AuthorizationSet expected_hw_enforced,  //
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index 4d7f1b8..641a227 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -22,6 +22,7 @@
 #include <algorithm>
 #include <iostream>
 
+#include <openssl/curve25519.h>
 #include <openssl/ec.h>
 #include <openssl/evp.h>
 #include <openssl/mem.h>
@@ -69,7 +70,17 @@
 
 namespace {
 
-bool check_patchLevels = false;
+// Maximum supported Ed25519 message size.
+const size_t MAX_ED25519_MSG_SIZE = 16 * 1024;
+
+// Whether to check that BOOT_PATCHLEVEL is populated.
+bool check_boot_pl = true;
+
+// The maximum number of times we'll attempt to verify that corruption
+// of an encrypted blob results in an error. Retries are necessary as there
+// is a small (roughly 1/256) chance that corrupting ciphertext still results
+// in valid PKCS7 padding.
+constexpr size_t kMaxPaddingCorruptionRetries = 8;
 
 template <TagType tag_type, Tag tag, typename ValueT>
 bool contains(const vector<KeyParameter>& set, TypedTag<tag_type, tag> ttag,
@@ -408,6 +419,126 @@
         // } end SEQUENCE (PrivateKeyInfo)
 );
 
+/**
+ * Ed25519 key pair generated as follows:
+ * ```
+ * % openssl req -x509 -newkey ED25519 -days 700 -nodes \
+ *  -keyout ed25519_priv.key -out ed25519.pem * -subj "/CN=fake.ed25519.com"
+ * Generating a ED25519 private key writing new private key to
+ * 'ed25519_priv.key'
+ * -----
+ * % cat ed25519_priv.key
+ * -----BEGIN PRIVATE KEY-----
+ * MC4CAQAwBQYDK2VwBCIEIKl3A5quNywcj1P+0XI9SBalFPIvO52NxceMLRH6dVmR
+ * -----END PRIVATE KEY-----
+ * % der2ascii -pem -i ed25519_priv.key
+ * SEQUENCE {
+ *   INTEGER { 0 }
+ *   SEQUENCE {
+ *     # ed25519
+ *     OBJECT_IDENTIFIER { 1.3.101.112 }
+ *   }
+ *   OCTET_STRING {
+ *     OCTET_STRING { `a977039aae372c1c8f53fed1723d4816a514f22f3b9d8dc5c78c2d11fa755991` }
+ *   }
+ * }
+ * % cat ed25519.pem
+ * -----BEGIN CERTIFICATE-----
+ * MIIBSjCB/aADAgECAhR0Jron3eKcdgqyecv/eEfGWAzn8DAFBgMrZXAwGzEZMBcG
+ * A1UEAwwQZmFrZS5lZDI1NTE5LmNvbTAeFw0yMTEwMjAwODI3NDJaFw0yMzA5MjAw
+ * ODI3NDJaMBsxGTAXBgNVBAMMEGZha2UuZWQyNTUxOS5jb20wKjAFBgMrZXADIQDv
+ * uwHz+3TaQ69D2digxlz0fFfsZg0rPqgQae3jBPRWkaNTMFEwHQYDVR0OBBYEFN9O
+ * od30SY4JTs66ZR403UPya+iXMB8GA1UdIwQYMBaAFN9Ood30SY4JTs66ZR403UPy
+ * a+iXMA8GA1UdEwEB/wQFMAMBAf8wBQYDK2VwA0EAKjVrYQjuE/gEL2j/ABpDbFjV
+ * Ilg5tJ6MN/P3psAv3Cs7f0X1lFqdlt15nJ/6aj2cmGCwNRXt5wcyYDKNu+v2Dw==
+ * -----END CERTIFICATE-----
+ * % openssl x509 -in ed25519.pem -text -noout
+ * Certificate:
+ *     Data:
+ *         Version: 3 (0x2)
+ *         Serial Number:
+ *             74:26:ba:27:dd:e2:9c:76:0a:b2:79:cb:ff:78:47:c6:58:0c:e7:f0
+ *         Signature Algorithm: ED25519
+ *         Issuer: CN = fake.ed25519.com
+ *         Validity
+ *             Not Before: Oct 20 08:27:42 2021 GMT
+ *             Not After : Sep 20 08:27:42 2023 GMT
+ *         Subject: CN = fake.ed25519.com
+ *         Subject Public Key Info:
+ *             Public Key Algorithm: ED25519
+ *                 ED25519 Public-Key:
+ *                 pub:
+ *                     ef:bb:01:f3:fb:74:da:43:af:43:d9:d8:a0:c6:5c:
+ *                     f4:7c:57:ec:66:0d:2b:3e:a8:10:69:ed:e3:04:f4:
+ *                     56:91
+ *         X509v3 extensions:
+ *             X509v3 Subject Key Identifier:
+ *                 DF:4E:A1:DD:F4:49:8E:09:4E:CE:BA:65:1E:34:DD:43:F2:6B:E8:97
+ *             X509v3 Authority Key Identifier:
+ *                 keyid:DF:4E:A1:DD:F4:49:8E:09:4E:CE:BA:65:1E:34:DD:43:F2:6B:E8:97
+ *
+ *             X509v3 Basic Constraints: critical
+ *                 CA:TRUE
+ *     Signature Algorithm: ED25519
+ *          2a:35:6b:61:08:ee:13:f8:04:2f:68:ff:00:1a:43:6c:58:d5:
+ *          22:58:39:b4:9e:8c:37:f3:f7:a6:c0:2f:dc:2b:3b:7f:45:f5:
+ *          94:5a:9d:96:dd:79:9c:9f:fa:6a:3d:9c:98:60:b0:35:15:ed:
+ *          e7:07:32:60:32:8d:bb:eb:f6:0f
+ * ```
+ */
+string ed25519_key = hex2str("a977039aae372c1c8f53fed1723d4816a514f22f3b9d8dc5c78c2d11fa755991");
+string ed25519_pkcs8_key = hex2str(
+        // RFC 5208 s5
+        "302e"    // SEQUENCE length 0x2e (PrivateKeyInfo) {
+        "0201"    // INTEGER length 1 (Version)
+        "00"      // version 0
+        "3005"    // SEQUENCE length 05 (AlgorithmIdentifier) {
+        "0603"    // OBJECT IDENTIFIER length 3 (algorithm)
+        "2b6570"  // 1.3.101.112 (id-Ed125519 RFC 8410 s3)
+        // } end SEQUENCE (AlgorithmIdentifier)
+        "0422"  // OCTET STRING length 0x22 (PrivateKey)
+        "0420"  // OCTET STRING length 0x20 (RFC 8410 s7)
+        "a977039aae372c1c8f53fed1723d4816a514f22f3b9d8dc5c78c2d11fa755991"
+        // } end SEQUENCE (PrivateKeyInfo)
+);
+string ed25519_pubkey = hex2str("efbb01f3fb74da43af43d9d8a0c65cf47c57ec660d2b3ea81069ede304f45691");
+
+/**
+ * X25519 key pair generated as follows:
+ * ```
+ * % openssl genpkey -algorithm X25519 > x25519_priv.key
+ * % cat x25519_priv.key
+ * -----BEGIN PRIVATE KEY-----
+ * MC4CAQAwBQYDK2VuBCIEIGgPwF3NLwQx/Sfwr2nfJvXitwlDNh3Skzh+TISN/y1C
+ * -----END PRIVATE KEY-----
+ * % der2ascii -pem -i x25519_priv.key
+ * SEQUENCE {
+ *   INTEGER { 0 }
+ *   SEQUENCE {
+ *     # x25519
+ *     OBJECT_IDENTIFIER { 1.3.101.110 }
+ *   }
+ *   OCTET_STRING {
+ *     OCTET_STRING { `680fc05dcd2f0431fd27f0af69df26f5e2b70943361dd293387e4c848dff2d42` }
+ *   }
+ * }
+ * ```
+ */
+
+string x25519_key = hex2str("680fc05dcd2f0431fd27f0af69df26f5e2b70943361dd293387e4c848dff2d42");
+string x25519_pkcs8_key = hex2str(
+        // RFC 5208 s5
+        "302e"    // SEQUENCE length 0x2e (PrivateKeyInfo) {
+        "0201"    // INTEGER length 1 (Version)
+        "00"      // version 0
+        "3005"    // SEQUENCE length 05 (AlgorithmIdentifier) {
+        "0603"    // OBJECT IDENTIFIER length 3 (algorithm)
+        "2b656e"  // 1.3.101.110 (id-X125519 RFC 8410 s3)
+        "0422"    // OCTET STRING length 0x22 (PrivateKey)
+        "0420"    // OCTET STRING length 0x20 (RFC 8410 s7)
+        "680fc05dcd2f0431fd27f0af69df26f5e2b70943361dd293387e4c848dff2d42");
+string x25519_pubkey = hex2str("be46925a857f17831d6d454b9d3d36a4a30166edf80eb82b684661c3e258f768");
+
 struct RSA_Delete {
     void operator()(RSA* p) { RSA_free(p); }
 };
@@ -523,11 +654,14 @@
         EXPECT_TRUE(os_pl);
         EXPECT_EQ(*os_pl, os_patch_level());
 
-        if (check_patchLevels) {
-            // Should include vendor and boot patchlevels.
-            auto vendor_pl = auths.GetTagValue(TAG_VENDOR_PATCHLEVEL);
-            EXPECT_TRUE(vendor_pl);
-            EXPECT_EQ(*vendor_pl, vendor_patch_level());
+        // Should include vendor patchlevel.
+        auto vendor_pl = auths.GetTagValue(TAG_VENDOR_PATCHLEVEL);
+        EXPECT_TRUE(vendor_pl);
+        EXPECT_EQ(*vendor_pl, vendor_patch_level());
+
+        // Should include boot patchlevel (but there are some test scenarios where this is not
+        // possible).
+        if (check_boot_pl) {
             auto boot_pl = auths.GetTagValue(TAG_BOOT_PATCHLEVEL);
             EXPECT_TRUE(boot_pl);
         }
@@ -884,6 +1018,37 @@
 }
 
 /*
+ * NewKeyGenerationTest.RsaWithMissingValidity
+ *
+ * Verifies that keymint returns an error while generating asymmetric key
+ * without providing NOT_BEFORE and NOT_AFTER parameters.
+ */
+TEST_P(NewKeyGenerationTest, RsaWithMissingValidity) {
+    // Per RFC 5280 4.1.2.5, an undefined expiration (not-after) field should be set to
+    // GeneralizedTime 999912312359559, which is 253402300799000 ms from Jan 1, 1970.
+    constexpr uint64_t kUndefinedExpirationDateTime = 253402300799000;
+
+    vector<uint8_t> key_blob;
+    vector<KeyCharacteristics> key_characteristics;
+    ASSERT_EQ(ErrorCode::MISSING_NOT_BEFORE,
+              GenerateKey(AuthorizationSetBuilder()
+                                  .RsaSigningKey(2048, 65537)
+                                  .Digest(Digest::NONE)
+                                  .Padding(PaddingMode::NONE)
+                                  .Authorization(TAG_CERTIFICATE_NOT_AFTER,
+                                                 kUndefinedExpirationDateTime),
+                          &key_blob, &key_characteristics));
+
+    ASSERT_EQ(ErrorCode::MISSING_NOT_AFTER,
+              GenerateKey(AuthorizationSetBuilder()
+                                  .RsaSigningKey(2048, 65537)
+                                  .Digest(Digest::NONE)
+                                  .Padding(PaddingMode::NONE)
+                                  .Authorization(TAG_CERTIFICATE_NOT_BEFORE, 0),
+                          &key_blob, &key_characteristics));
+}
+
+/*
  * NewKeyGenerationTest.RsaWithAttestation
  *
  * Verifies that keymint can generate all required RSA key sizes with attestation, and that the
@@ -902,19 +1067,30 @@
     for (auto key_size : ValidKeySizes(Algorithm::RSA)) {
         vector<uint8_t> key_blob;
         vector<KeyCharacteristics> key_characteristics;
-        ASSERT_EQ(ErrorCode::OK,
-                  GenerateKey(AuthorizationSetBuilder()
-                                      .RsaSigningKey(key_size, 65537)
-                                      .Digest(Digest::NONE)
-                                      .Padding(PaddingMode::NONE)
-                                      .AttestationChallenge(challenge)
-                                      .AttestationApplicationId(app_id)
-                                      .Authorization(TAG_NO_AUTH_REQUIRED)
-                                      .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
-                                      .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
-                                      .SetDefaultValidity(),
-                              &key_blob, &key_characteristics));
+        auto builder = AuthorizationSetBuilder()
+                               .RsaSigningKey(key_size, 65537)
+                               .Digest(Digest::NONE)
+                               .Padding(PaddingMode::NONE)
+                               .AttestationChallenge(challenge)
+                               .AttestationApplicationId(app_id)
+                               .Authorization(TAG_NO_AUTH_REQUIRED)
+                               .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+                               .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+                               .SetDefaultValidity();
 
+        auto result = GenerateKey(builder, &key_blob, &key_characteristics);
+        // Strongbox may not support factory provisioned attestation key.
+        if (SecLevel() == SecurityLevel::STRONGBOX) {
+            if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) {
+                result = GenerateKeyWithSelfSignedAttestKey(
+                        AuthorizationSetBuilder()
+                                .RsaKey(key_size, 65537)
+                                .AttestKey()
+                                .SetDefaultValidity(), /* attest key params */
+                        builder, &key_blob, &key_characteristics);
+            }
+        }
+        ASSERT_EQ(ErrorCode::OK, result);
         ASSERT_GT(key_blob.size(), 0U);
         CheckBaseParams(key_characteristics);
         CheckCharacteristics(key_blob, key_characteristics);
@@ -932,7 +1108,7 @@
 
         AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
         AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
-        EXPECT_TRUE(verify_attestation_record(challenge, app_id,  //
+        EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id,  //
                                               sw_enforced, hw_enforced, SecLevel(),
                                               cert_chain_[0].encodedCertificate));
 
@@ -1035,17 +1211,29 @@
 
     vector<uint8_t> key_blob;
     vector<KeyCharacteristics> key_characteristics;
-    ASSERT_EQ(ErrorCode::OK,
-              GenerateKey(AuthorizationSetBuilder()
-                                  .RsaEncryptionKey(key_size, 65537)
-                                  .Padding(PaddingMode::NONE)
-                                  .AttestationChallenge(challenge)
-                                  .AttestationApplicationId(app_id)
-                                  .Authorization(TAG_NO_AUTH_REQUIRED)
-                                  .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
-                                  .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
-                                  .SetDefaultValidity(),
-                          &key_blob, &key_characteristics));
+    auto builder = AuthorizationSetBuilder()
+                           .RsaEncryptionKey(key_size, 65537)
+                           .Padding(PaddingMode::NONE)
+                           .AttestationChallenge(challenge)
+                           .AttestationApplicationId(app_id)
+                           .Authorization(TAG_NO_AUTH_REQUIRED)
+                           .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+                           .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+                           .SetDefaultValidity();
+
+    auto result = GenerateKey(builder, &key_blob, &key_characteristics);
+    // Strongbox may not support factory provisioned attestation key.
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) {
+            result = GenerateKeyWithSelfSignedAttestKey(
+                    AuthorizationSetBuilder()
+                            .RsaKey(key_size, 65537)
+                            .AttestKey()
+                            .SetDefaultValidity(), /* attest key params */
+                    builder, &key_blob, &key_characteristics);
+        }
+    }
+    ASSERT_EQ(ErrorCode::OK, result);
 
     ASSERT_GT(key_blob.size(), 0U);
     AuthorizationSet auths;
@@ -1083,7 +1271,7 @@
 
     AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
     AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
-    EXPECT_TRUE(verify_attestation_record(challenge, app_id,  //
+    EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id,  //
                                           sw_enforced, hw_enforced, SecLevel(),
                                           cert_chain_[0].encodedCertificate));
 
@@ -1147,15 +1335,27 @@
     vector<uint8_t> key_blob;
     vector<KeyCharacteristics> key_characteristics;
 
-    ASSERT_EQ(ErrorCode::ATTESTATION_APPLICATION_ID_MISSING,
-              GenerateKey(AuthorizationSetBuilder()
-                                  .RsaSigningKey(2048, 65537)
-                                  .Digest(Digest::NONE)
-                                  .Padding(PaddingMode::NONE)
-                                  .AttestationChallenge(challenge)
-                                  .Authorization(TAG_NO_AUTH_REQUIRED)
-                                  .SetDefaultValidity(),
-                          &key_blob, &key_characteristics));
+    auto builder = AuthorizationSetBuilder()
+                           .RsaSigningKey(2048, 65537)
+                           .Digest(Digest::NONE)
+                           .Padding(PaddingMode::NONE)
+                           .AttestationChallenge(challenge)
+                           .Authorization(TAG_NO_AUTH_REQUIRED)
+                           .SetDefaultValidity();
+
+    auto result = GenerateKey(builder, &key_blob, &key_characteristics);
+    // Strongbox may not support factory provisioned attestation key.
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) {
+            result = GenerateKeyWithSelfSignedAttestKey(
+                    AuthorizationSetBuilder()
+                            .RsaKey(2048, 65537)
+                            .AttestKey()
+                            .SetDefaultValidity(), /* attest key params */
+                    builder, &key_blob, &key_characteristics);
+        }
+    }
+    ASSERT_EQ(ErrorCode::ATTESTATION_APPLICATION_ID_MISSING, result);
 }
 
 /*
@@ -1265,19 +1465,31 @@
     for (auto key_size : ValidKeySizes(Algorithm::RSA)) {
         vector<uint8_t> key_blob;
         vector<KeyCharacteristics> key_characteristics;
-        ASSERT_EQ(ErrorCode::OK,
-                  GenerateKey(AuthorizationSetBuilder()
-                                      .RsaSigningKey(key_size, 65537)
-                                      .Digest(Digest::NONE)
-                                      .Padding(PaddingMode::NONE)
-                                      .AttestationChallenge(challenge)
-                                      .AttestationApplicationId(app_id)
-                                      .Authorization(TAG_NO_AUTH_REQUIRED)
-                                      .Authorization(TAG_USAGE_COUNT_LIMIT, 1)
-                                      .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
-                                      .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
-                                      .SetDefaultValidity(),
-                              &key_blob, &key_characteristics));
+        auto builder = AuthorizationSetBuilder()
+                               .RsaSigningKey(key_size, 65537)
+                               .Digest(Digest::NONE)
+                               .Padding(PaddingMode::NONE)
+                               .AttestationChallenge(challenge)
+                               .AttestationApplicationId(app_id)
+                               .Authorization(TAG_NO_AUTH_REQUIRED)
+                               .Authorization(TAG_USAGE_COUNT_LIMIT, 1)
+                               .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+                               .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+                               .SetDefaultValidity();
+
+        auto result = GenerateKey(builder, &key_blob, &key_characteristics);
+        // Strongbox may not support factory provisioned attestation key.
+        if (SecLevel() == SecurityLevel::STRONGBOX) {
+            if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) {
+                result = GenerateKeyWithSelfSignedAttestKey(
+                        AuthorizationSetBuilder()
+                                .RsaKey(key_size, 65537)
+                                .AttestKey()
+                                .SetDefaultValidity(), /* attest key params */
+                        builder, &key_blob, &key_characteristics);
+            }
+        }
+        ASSERT_EQ(ErrorCode::OK, result);
 
         ASSERT_GT(key_blob.size(), 0U);
         CheckBaseParams(key_characteristics);
@@ -1305,7 +1517,7 @@
 
         AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
         AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
-        EXPECT_TRUE(verify_attestation_record(challenge, app_id,  //
+        EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id,  //
                                               sw_enforced, hw_enforced, SecLevel(),
                                               cert_chain_[0].encodedCertificate));
 
@@ -1364,7 +1576,7 @@
 /*
  * NewKeyGenerationTest.Ecdsa
  *
- * Verifies that keymint can generate all required EC key sizes, and that the resulting keys
+ * Verifies that keymint can generate all required EC curves, and that the resulting keys
  * have correct characteristics.
  */
 TEST_P(NewKeyGenerationTest, Ecdsa) {
@@ -1390,6 +1602,94 @@
 }
 
 /*
+ * NewKeyGenerationTest.EcdsaCurve25519
+ *
+ * Verifies that keymint can generate a curve25519 key, and that the resulting key
+ * has correct characteristics.
+ */
+TEST_P(NewKeyGenerationTest, EcdsaCurve25519) {
+    if (!Curve25519Supported()) {
+        GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+    }
+
+    EcCurve curve = EcCurve::CURVE_25519;
+    vector<uint8_t> key_blob;
+    vector<KeyCharacteristics> key_characteristics;
+    ErrorCode result = GenerateKey(AuthorizationSetBuilder()
+                                           .EcdsaSigningKey(curve)
+                                           .Digest(Digest::NONE)
+                                           .SetDefaultValidity(),
+                                   &key_blob, &key_characteristics);
+    ASSERT_EQ(result, ErrorCode::OK);
+    ASSERT_GT(key_blob.size(), 0U);
+
+    EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
+    ASSERT_GT(cert_chain_.size(), 0);
+
+    CheckBaseParams(key_characteristics);
+    CheckCharacteristics(key_blob, key_characteristics);
+
+    AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
+
+    EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::EC));
+    EXPECT_TRUE(crypto_params.Contains(TAG_EC_CURVE, curve)) << "Curve " << curve << "missing";
+
+    CheckedDeleteKey(&key_blob);
+}
+
+/*
+ * NewKeyGenerationTest.EcCurve25519MultiPurposeFail
+ *
+ * Verifies that KeyMint rejects an attempt to generate a curve 25519 key for both
+ * SIGN and AGREE_KEY.
+ */
+TEST_P(NewKeyGenerationTest, EcdsaCurve25519MultiPurposeFail) {
+    if (!Curve25519Supported()) {
+        GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+    }
+
+    EcCurve curve = EcCurve::CURVE_25519;
+    vector<uint8_t> key_blob;
+    vector<KeyCharacteristics> key_characteristics;
+    ErrorCode result = GenerateKey(AuthorizationSetBuilder()
+                                           .Authorization(TAG_PURPOSE, KeyPurpose::AGREE_KEY)
+                                           .EcdsaSigningKey(curve)
+                                           .Digest(Digest::NONE)
+                                           .SetDefaultValidity(),
+                                   &key_blob, &key_characteristics);
+    ASSERT_EQ(result, ErrorCode::INCOMPATIBLE_PURPOSE);
+}
+
+/*
+ * NewKeyGenerationTest.EcdsaWithMissingValidity
+ *
+ * Verifies that keymint returns an error while generating asymmetric key
+ * without providing NOT_BEFORE and NOT_AFTER parameters.
+ */
+TEST_P(NewKeyGenerationTest, EcdsaWithMissingValidity) {
+    // Per RFC 5280 4.1.2.5, an undefined expiration (not-after) field should be set to
+    // GeneralizedTime 999912312359559, which is 253402300799000 ms from Jan 1, 1970.
+    constexpr uint64_t kUndefinedExpirationDateTime = 253402300799000;
+
+    vector<uint8_t> key_blob;
+    vector<KeyCharacteristics> key_characteristics;
+    ASSERT_EQ(ErrorCode::MISSING_NOT_BEFORE,
+              GenerateKey(AuthorizationSetBuilder()
+                                  .EcdsaSigningKey(EcCurve::P_256)
+                                  .Digest(Digest::NONE)
+                                  .Authorization(TAG_CERTIFICATE_NOT_AFTER,
+                                                 kUndefinedExpirationDateTime),
+                          &key_blob, &key_characteristics));
+
+    ASSERT_EQ(ErrorCode::MISSING_NOT_AFTER,
+              GenerateKey(AuthorizationSetBuilder()
+                                  .EcdsaSigningKey(EcCurve::P_256)
+                                  .Digest(Digest::NONE)
+                                  .Authorization(TAG_CERTIFICATE_NOT_BEFORE, 0),
+                          &key_blob, &key_characteristics));
+}
+
+/*
  * NewKeyGenerationTest.EcdsaAttestation
  *
  * Verifies that for all Ecdsa key sizes, if challenge and app id is provided,
@@ -1408,17 +1708,29 @@
     for (auto curve : ValidCurves()) {
         vector<uint8_t> key_blob;
         vector<KeyCharacteristics> key_characteristics;
-        ASSERT_EQ(ErrorCode::OK,
-                  GenerateKey(AuthorizationSetBuilder()
-                                      .Authorization(TAG_NO_AUTH_REQUIRED)
-                                      .EcdsaSigningKey(curve)
-                                      .Digest(Digest::NONE)
-                                      .AttestationChallenge(challenge)
-                                      .AttestationApplicationId(app_id)
-                                      .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
-                                      .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
-                                      .SetDefaultValidity(),
-                              &key_blob, &key_characteristics));
+        auto builder = AuthorizationSetBuilder()
+                               .Authorization(TAG_NO_AUTH_REQUIRED)
+                               .EcdsaSigningKey(curve)
+                               .Digest(Digest::NONE)
+                               .AttestationChallenge(challenge)
+                               .AttestationApplicationId(app_id)
+                               .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+                               .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+                               .SetDefaultValidity();
+
+        auto result = GenerateKey(builder, &key_blob, &key_characteristics);
+        // Strongbox may not support factory provisioned attestation key.
+        if (SecLevel() == SecurityLevel::STRONGBOX) {
+            if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) {
+                result = GenerateKeyWithSelfSignedAttestKey(
+                        AuthorizationSetBuilder()
+                                .EcdsaKey(curve)
+                                .AttestKey()
+                                .SetDefaultValidity(), /* attest key params */
+                        builder, &key_blob, &key_characteristics);
+            }
+        }
+        ASSERT_EQ(ErrorCode::OK, result);
         ASSERT_GT(key_blob.size(), 0U);
         CheckBaseParams(key_characteristics);
         CheckCharacteristics(key_blob, key_characteristics);
@@ -1434,7 +1746,7 @@
 
         AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
         AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
-        EXPECT_TRUE(verify_attestation_record(challenge, app_id,  //
+        EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id,  //
                                               sw_enforced, hw_enforced, SecLevel(),
                                               cert_chain_[0].encodedCertificate));
 
@@ -1443,6 +1755,62 @@
 }
 
 /*
+ * NewKeyGenerationTest.EcdsaAttestationCurve25519
+ *
+ * Verifies that for a curve 25519 key, if challenge and app id is provided,
+ * an attestation will be generated.
+ */
+TEST_P(NewKeyGenerationTest, EcdsaAttestationCurve25519) {
+    if (!Curve25519Supported()) {
+        GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+    }
+
+    EcCurve curve = EcCurve::CURVE_25519;
+    auto challenge = "hello";
+    auto app_id = "foo";
+
+    auto subject = "cert subj 2";
+    vector<uint8_t> subject_der(make_name_from_str(subject));
+
+    uint64_t serial_int = 0xFFFFFFFFFFFFFFFF;
+    vector<uint8_t> serial_blob(build_serial_blob(serial_int));
+
+    vector<uint8_t> key_blob;
+    vector<KeyCharacteristics> key_characteristics;
+    ErrorCode result = GenerateKey(AuthorizationSetBuilder()
+                                           .Authorization(TAG_NO_AUTH_REQUIRED)
+                                           .EcdsaSigningKey(curve)
+                                           .Digest(Digest::NONE)
+                                           .AttestationChallenge(challenge)
+                                           .AttestationApplicationId(app_id)
+                                           .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+                                           .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+                                           .SetDefaultValidity(),
+                                   &key_blob, &key_characteristics);
+    ASSERT_EQ(ErrorCode::OK, result);
+    ASSERT_GT(key_blob.size(), 0U);
+    CheckBaseParams(key_characteristics);
+    CheckCharacteristics(key_blob, key_characteristics);
+
+    AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
+
+    EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::EC));
+    EXPECT_TRUE(crypto_params.Contains(TAG_EC_CURVE, curve)) << "Curve " << curve << "missing";
+
+    EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
+    ASSERT_GT(cert_chain_.size(), 0);
+    verify_subject_and_serial(cert_chain_[0], serial_int, subject, false);
+
+    AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
+    AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
+    EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id,  //
+                                          sw_enforced, hw_enforced, SecLevel(),
+                                          cert_chain_[0].encodedCertificate));
+
+    CheckedDeleteKey(&key_blob);
+}
+
+/*
  * NewKeyGenerationTest.EcdsaAttestationTags
  *
  * Verifies that creation of an attested ECDSA key includes various tags in the
@@ -1480,6 +1848,7 @@
                               .Authorization(TAG_TRUSTED_CONFIRMATION_REQUIRED)
                               .Authorization(TAG_UNLOCKED_DEVICE_REQUIRED)
                               .Authorization(TAG_CREATION_DATETIME, 1619621648000);
+
     for (const KeyParameter& tag : extra_tags) {
         SCOPED_TRACE(testing::Message() << "tag-" << tag);
         vector<uint8_t> key_blob;
@@ -1495,6 +1864,17 @@
             // Tag not required to be supported by all KeyMint implementations.
             continue;
         }
+        // Strongbox may not support factory provisioned attestation key.
+        if (SecLevel() == SecurityLevel::STRONGBOX) {
+            if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) {
+                result = GenerateKeyWithSelfSignedAttestKey(
+                        AuthorizationSetBuilder()
+                                .EcdsaKey(EcCurve::P_256)
+                                .AttestKey()
+                                .SetDefaultValidity(), /* attest key params */
+                        builder, &key_blob, &key_characteristics);
+            }
+        }
         ASSERT_EQ(result, ErrorCode::OK);
         ASSERT_GT(key_blob.size(), 0U);
 
@@ -1512,25 +1892,26 @@
 
         // Verifying the attestation record will check for the specific tag because
         // it's included in the authorizations.
-        EXPECT_TRUE(verify_attestation_record(challenge, app_id, sw_enforced, hw_enforced,
-                                              SecLevel(), cert_chain_[0].encodedCertificate));
+        EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id, sw_enforced,
+                                              hw_enforced, SecLevel(),
+                                              cert_chain_[0].encodedCertificate));
 
         CheckedDeleteKey(&key_blob);
     }
 
-    // Device attestation IDs should be rejected for normal attestation requests; these fields
-    // are only used for device unique attestation.
-    auto invalid_tags = AuthorizationSetBuilder()
-                                .Authorization(TAG_ATTESTATION_ID_BRAND, "brand")
-                                .Authorization(TAG_ATTESTATION_ID_DEVICE, "device")
-                                .Authorization(TAG_ATTESTATION_ID_PRODUCT, "product")
-                                .Authorization(TAG_ATTESTATION_ID_SERIAL, "serial")
-                                .Authorization(TAG_ATTESTATION_ID_IMEI, "imei")
-                                .Authorization(TAG_ATTESTATION_ID_MEID, "meid")
-                                .Authorization(TAG_ATTESTATION_ID_MANUFACTURER, "manufacturer")
-                                .Authorization(TAG_ATTESTATION_ID_MODEL, "model");
+    // Collection of invalid attestation ID tags.
+    auto invalid_tags =
+            AuthorizationSetBuilder()
+                    .Authorization(TAG_ATTESTATION_ID_BRAND, "bogus-brand")
+                    .Authorization(TAG_ATTESTATION_ID_DEVICE, "devious-device")
+                    .Authorization(TAG_ATTESTATION_ID_PRODUCT, "punctured-product")
+                    .Authorization(TAG_ATTESTATION_ID_SERIAL, "suspicious-serial")
+                    .Authorization(TAG_ATTESTATION_ID_IMEI, "invalid-imei")
+                    .Authorization(TAG_ATTESTATION_ID_MEID, "mismatching-meid")
+                    .Authorization(TAG_ATTESTATION_ID_MANUFACTURER, "malformed-manufacturer")
+                    .Authorization(TAG_ATTESTATION_ID_MODEL, "malicious-model");
     for (const KeyParameter& tag : invalid_tags) {
-        SCOPED_TRACE(testing::Message() << "tag-" << tag);
+        SCOPED_TRACE(testing::Message() << "-incorrect-tag-" << tag);
         vector<uint8_t> key_blob;
         vector<KeyCharacteristics> key_characteristics;
         AuthorizationSetBuilder builder =
@@ -1544,8 +1925,98 @@
                         .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
                         .SetDefaultValidity();
         builder.push_back(tag);
-        ASSERT_EQ(ErrorCode::CANNOT_ATTEST_IDS,
-                  GenerateKey(builder, &key_blob, &key_characteristics));
+
+        auto error = GenerateKey(builder, &key_blob, &key_characteristics);
+        // Strongbox may not support factory provisioned attestation key.
+        if (SecLevel() == SecurityLevel::STRONGBOX) {
+            if (error == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) {
+                error = GenerateKeyWithSelfSignedAttestKey(
+                        AuthorizationSetBuilder()
+                                .EcdsaKey(EcCurve::P_256)
+                                .AttestKey()
+                                .SetDefaultValidity(), /* attest key params */
+                        builder, &key_blob, &key_characteristics);
+            }
+        }
+        ASSERT_EQ(error, ErrorCode::CANNOT_ATTEST_IDS);
+    }
+}
+
+/*
+ * NewKeyGenerationTest.EcdsaAttestationIdTags
+ *
+ * Verifies that creation of an attested ECDSA key includes various ID tags in the
+ * attestation extension.
+ */
+TEST_P(NewKeyGenerationTest, EcdsaAttestationIdTags) {
+    if (is_gsi_image()) {
+        // GSI sets up a standard set of device identifiers that may not match
+        // the device identifiers held by the device.
+        GTEST_SKIP() << "Test not applicable under GSI";
+    }
+    auto challenge = "hello";
+    auto app_id = "foo";
+    auto subject = "cert subj 2";
+    vector<uint8_t> subject_der(make_name_from_str(subject));
+    uint64_t serial_int = 0x1010;
+    vector<uint8_t> serial_blob(build_serial_blob(serial_int));
+    const AuthorizationSetBuilder base_builder =
+            AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .EcdsaSigningKey(EcCurve::P_256)
+                    .Digest(Digest::NONE)
+                    .AttestationChallenge(challenge)
+                    .AttestationApplicationId(app_id)
+                    .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+                    .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+                    .SetDefaultValidity();
+
+    // Various ATTESTATION_ID_* tags that map to fields in the attestation extension ASN.1 schema.
+    auto extra_tags = AuthorizationSetBuilder();
+    add_tag_from_prop(&extra_tags, TAG_ATTESTATION_ID_BRAND, "ro.product.brand");
+    add_tag_from_prop(&extra_tags, TAG_ATTESTATION_ID_DEVICE, "ro.product.device");
+    add_tag_from_prop(&extra_tags, TAG_ATTESTATION_ID_PRODUCT, "ro.product.name");
+    add_tag_from_prop(&extra_tags, TAG_ATTESTATION_ID_SERIAL, "ro.serial");
+    add_tag_from_prop(&extra_tags, TAG_ATTESTATION_ID_MANUFACTURER, "ro.product.manufacturer");
+    add_tag_from_prop(&extra_tags, TAG_ATTESTATION_ID_MODEL, "ro.product.model");
+
+    for (const KeyParameter& tag : extra_tags) {
+        SCOPED_TRACE(testing::Message() << "tag-" << tag);
+        vector<uint8_t> key_blob;
+        vector<KeyCharacteristics> key_characteristics;
+        AuthorizationSetBuilder builder = base_builder;
+        builder.push_back(tag);
+        auto result = GenerateKey(builder, &key_blob, &key_characteristics);
+        // Strongbox may not support factory provisioned attestation key.
+        if (SecLevel() == SecurityLevel::STRONGBOX) {
+            if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+        }
+        if (result == ErrorCode::CANNOT_ATTEST_IDS && !isDeviceIdAttestationRequired()) {
+            // ID attestation was optional till api level 32, from api level 33 it is mandatory.
+            continue;
+        }
+        ASSERT_EQ(result, ErrorCode::OK);
+        ASSERT_GT(key_blob.size(), 0U);
+
+        EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
+        ASSERT_GT(cert_chain_.size(), 0);
+        verify_subject_and_serial(cert_chain_[0], serial_int, subject, /* self_signed = */ false);
+
+        AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
+        AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
+
+        // The attested key characteristics will not contain APPLICATION_ID_* fields (their
+        // spec definitions all have "Must never appear in KeyCharacteristics"), but the
+        // attestation extension should contain them, so make sure the extra tag is added.
+        hw_enforced.push_back(tag);
+
+        // Verifying the attestation record will check for the specific tag because
+        // it's included in the authorizations.
+        EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id, sw_enforced,
+                                              hw_enforced, SecLevel(),
+                                              cert_chain_[0].encodedCertificate));
+
+        CheckedDeleteKey(&key_blob);
     }
 }
 
@@ -1577,8 +2048,18 @@
         if (reset) {
             builder.Authorization(TAG_RESET_SINCE_ID_ROTATION);
         }
-
-        ASSERT_EQ(ErrorCode::OK, GenerateKey(builder));
+        auto result = GenerateKey(builder);
+        if (SecLevel() == SecurityLevel::STRONGBOX) {
+            if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) {
+                result = GenerateKeyWithSelfSignedAttestKey(
+                        AuthorizationSetBuilder()
+                                .EcdsaKey(EcCurve::P_256)
+                                .AttestKey()
+                                .SetDefaultValidity(), /* attest key params */
+                        builder, &key_blob_, &key_characteristics_, &cert_chain_);
+            }
+        }
+        ASSERT_EQ(ErrorCode::OK, result);
         ASSERT_GT(key_blob_.size(), 0U);
 
         EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
@@ -1589,9 +2070,9 @@
         AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics_);
 
         // Check that the unique ID field in the extension is non-empty.
-        EXPECT_TRUE(verify_attestation_record(challenge, app_id, sw_enforced, hw_enforced,
-                                              SecLevel(), cert_chain_[0].encodedCertificate,
-                                              unique_id));
+        EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id, sw_enforced,
+                                              hw_enforced, SecLevel(),
+                                              cert_chain_[0].encodedCertificate, unique_id));
         EXPECT_GT(unique_id->size(), 0);
         CheckedDeleteKey();
     };
@@ -1665,18 +2146,30 @@
     // to confirm that this field never makes it into the attestation extension.
     vector<uint8_t> key_blob;
     vector<KeyCharacteristics> key_characteristics;
-    auto result = GenerateKey(AuthorizationSetBuilder()
-                                      .Authorization(TAG_NO_AUTH_REQUIRED)
-                                      .EcdsaSigningKey(EcCurve::P_256)
-                                      .Digest(Digest::NONE)
-                                      .AttestationChallenge(challenge)
-                                      .AttestationApplicationId(attest_app_id)
-                                      .Authorization(TAG_APPLICATION_ID, "client_id")
-                                      .Authorization(TAG_APPLICATION_DATA, "appdata")
-                                      .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
-                                      .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
-                                      .SetDefaultValidity(),
-                              &key_blob, &key_characteristics);
+    auto builder = AuthorizationSetBuilder()
+                           .Authorization(TAG_NO_AUTH_REQUIRED)
+                           .EcdsaSigningKey(EcCurve::P_256)
+                           .Digest(Digest::NONE)
+                           .AttestationChallenge(challenge)
+                           .AttestationApplicationId(attest_app_id)
+                           .Authorization(TAG_APPLICATION_ID, "client_id")
+                           .Authorization(TAG_APPLICATION_DATA, "appdata")
+                           .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+                           .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+                           .SetDefaultValidity();
+
+    auto result = GenerateKey(builder, &key_blob, &key_characteristics);
+    // Strongbox may not support factory provisioned attestation key.
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) {
+            result = GenerateKeyWithSelfSignedAttestKey(
+                    AuthorizationSetBuilder()
+                            .EcdsaKey(EcCurve::P_256)
+                            .AttestKey()
+                            .SetDefaultValidity(), /* attest key params */
+                    builder, &key_blob, &key_characteristics);
+        }
+    }
     ASSERT_EQ(result, ErrorCode::OK);
     ASSERT_GT(key_blob.size(), 0U);
 
@@ -1686,8 +2179,9 @@
 
     AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
     AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
-    EXPECT_TRUE(verify_attestation_record(challenge, attest_app_id, sw_enforced, hw_enforced,
-                                          SecLevel(), cert_chain_[0].encodedCertificate));
+    EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, attest_app_id, sw_enforced,
+                                          hw_enforced, SecLevel(),
+                                          cert_chain_[0].encodedCertificate));
 
     // Check that the app id is not in the cert.
     string app_id = "clientid";
@@ -1754,14 +2248,25 @@
     auto challenge = "hello";
     vector<uint8_t> key_blob;
     vector<KeyCharacteristics> key_characteristics;
+    auto builder = AuthorizationSetBuilder()
+                           .EcdsaSigningKey(EcCurve::P_256)
+                           .Digest(Digest::NONE)
+                           .AttestationChallenge(challenge)
+                           .SetDefaultValidity();
 
-    ASSERT_EQ(ErrorCode::ATTESTATION_APPLICATION_ID_MISSING,
-              GenerateKey(AuthorizationSetBuilder()
-                                  .EcdsaSigningKey(EcCurve::P_256)
-                                  .Digest(Digest::NONE)
-                                  .AttestationChallenge(challenge)
-                                  .SetDefaultValidity(),
-                          &key_blob, &key_characteristics));
+    auto result = GenerateKey(builder, &key_blob, &key_characteristics);
+    // Strongbox may not support factory provisioned attestation key.
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) {
+            result = GenerateKeyWithSelfSignedAttestKey(
+                    AuthorizationSetBuilder()
+                            .EcdsaKey(EcCurve::P_256)
+                            .AttestKey()
+                            .SetDefaultValidity(), /* attest key params */
+                    builder, &key_blob, &key_characteristics);
+        }
+    }
+    ASSERT_EQ(ErrorCode::ATTESTATION_APPLICATION_ID_MISSING, result);
 }
 
 /*
@@ -1818,14 +2323,27 @@
         const string app_id(length, 'a');
         vector<uint8_t> key_blob;
         vector<KeyCharacteristics> key_characteristics;
-        ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                                     .Authorization(TAG_NO_AUTH_REQUIRED)
-                                                     .EcdsaSigningKey(EcCurve::P_256)
-                                                     .Digest(Digest::NONE)
-                                                     .AttestationChallenge(challenge)
-                                                     .AttestationApplicationId(app_id)
-                                                     .SetDefaultValidity(),
-                                             &key_blob, &key_characteristics));
+        auto builder = AuthorizationSetBuilder()
+                               .Authorization(TAG_NO_AUTH_REQUIRED)
+                               .EcdsaSigningKey(EcCurve::P_256)
+                               .Digest(Digest::NONE)
+                               .AttestationChallenge(challenge)
+                               .AttestationApplicationId(app_id)
+                               .SetDefaultValidity();
+
+        auto result = GenerateKey(builder, &key_blob, &key_characteristics);
+        // Strongbox may not support factory provisioned attestation key.
+        if (SecLevel() == SecurityLevel::STRONGBOX) {
+            if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) {
+                result = GenerateKeyWithSelfSignedAttestKey(
+                        AuthorizationSetBuilder()
+                                .EcdsaKey(EcCurve::P_256)
+                                .AttestKey()
+                                .SetDefaultValidity(), /* attest key params */
+                        builder, &key_blob, &key_characteristics);
+            }
+        }
+        ASSERT_EQ(ErrorCode::OK, result);
         ASSERT_GT(key_blob.size(), 0U);
         CheckBaseParams(key_characteristics);
         CheckCharacteristics(key_blob, key_characteristics);
@@ -1840,7 +2358,7 @@
 
         AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
         AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
-        EXPECT_TRUE(verify_attestation_record(challenge, app_id,  //
+        EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id,  //
                                               sw_enforced, hw_enforced, SecLevel(),
                                               cert_chain_[0].encodedCertificate));
 
@@ -1902,20 +2420,22 @@
 }
 
 /*
- * NewKeyGenerationTest.EcdsaInvalidSize
+ * NewKeyGenerationTest.EcdsaInvalidCurve
  *
- * Verifies that specifying an invalid key size for EC key generation returns
+ * Verifies that specifying an invalid curve for EC key generation returns
  * UNSUPPORTED_KEY_SIZE.
  */
-TEST_P(NewKeyGenerationTest, EcdsaInvalidSize) {
+TEST_P(NewKeyGenerationTest, EcdsaInvalidCurve) {
     for (auto curve : InvalidCurves()) {
         vector<uint8_t> key_blob;
         vector<KeyCharacteristics> key_characteristics;
-        ASSERT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE, GenerateKey(AuthorizationSetBuilder()
-                                                                       .EcdsaSigningKey(curve)
-                                                                       .Digest(Digest::NONE)
-                                                                       .SetDefaultValidity(),
-                                                               &key_blob, &key_characteristics));
+        auto result = GenerateKey(AuthorizationSetBuilder()
+                                          .EcdsaSigningKey(curve)
+                                          .Digest(Digest::NONE)
+                                          .SetDefaultValidity(),
+                                  &key_blob, &key_characteristics);
+        ASSERT_TRUE(result == ErrorCode::UNSUPPORTED_KEY_SIZE ||
+                    result == ErrorCode::UNSUPPORTED_EC_CURVE);
     }
 
     ASSERT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE,
@@ -1928,13 +2448,38 @@
 }
 
 /*
+ * 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
  * INVALID_ARGUMENT.
  */
 TEST_P(NewKeyGenerationTest, EcdsaMismatchKeySize) {
-    if (SecLevel() == SecurityLevel::STRONGBOX) return;
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        GTEST_SKIP() << "Test not applicable to StrongBox device";
+    }
 
     auto result = GenerateKey(AuthorizationSetBuilder()
                                       .Authorization(TAG_ALGORITHM, Algorithm::EC)
@@ -2161,7 +2706,9 @@
  * Verifies that keymint rejects HMAC key generation with multiple specified digest algorithms.
  */
 TEST_P(NewKeyGenerationTest, HmacMultipleDigests) {
-    if (SecLevel() == SecurityLevel::STRONGBOX) return;
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        GTEST_SKIP() << "Test not applicable to StrongBox device";
+    }
 
     ASSERT_EQ(ErrorCode::UNSUPPORTED_DIGEST,
               GenerateKey(AuthorizationSetBuilder()
@@ -2385,7 +2932,9 @@
  * presented.
  */
 TEST_P(SigningOperationsTest, NoUserConfirmation) {
-    if (SecLevel() == SecurityLevel::STRONGBOX) return;
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        GTEST_SKIP() << "Test not applicable to StrongBox device";
+    }
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                                  .RsaSigningKey(1024, 65537)
                                                  .Digest(Digest::NONE)
@@ -2475,7 +3024,9 @@
  * for a 1024-bit key.
  */
 TEST_P(SigningOperationsTest, RsaPssSha512TooSmallKey) {
-    if (SecLevel() == SecurityLevel::STRONGBOX) return;
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        GTEST_SKIP() << "Test not applicable to StrongBox device";
+    }
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                                  .RsaSigningKey(1024, 65537)
                                                  .Digest(Digest::SHA_2_512)
@@ -2718,15 +3269,19 @@
 /*
  * SigningOperationsTest.EcdsaAllDigestsAndCurves
  *
- * Verifies ECDSA signature/verification for all digests and curves.
+ * Verifies ECDSA signature/verification for all digests and required curves.
  */
 TEST_P(SigningOperationsTest, EcdsaAllDigestsAndCurves) {
-    auto digests = ValidDigests(true /* withNone */, false /* withMD5 */);
 
     string message = "1234567890";
     string corrupt_message = "2234567890";
     for (auto curve : ValidCurves()) {
         SCOPED_TRACE(testing::Message() << "Curve::" << curve);
+        // Ed25519 only allows Digest::NONE.
+        auto digests = (curve == EcCurve::CURVE_25519)
+                               ? std::vector<Digest>(1, Digest::NONE)
+                               : ValidDigests(true /* withNone */, false /* withMD5 */);
+
         ErrorCode error = GenerateKey(AuthorizationSetBuilder()
                                               .Authorization(TAG_NO_AUTH_REQUIRED)
                                               .EcdsaSigningKey(curve)
@@ -2751,25 +3306,141 @@
 /*
  * SigningOperationsTest.EcdsaAllCurves
  *
- * Verifies that ECDSA operations succeed with all possible curves.
+ * Verifies that ECDSA operations succeed with all required curves.
  */
 TEST_P(SigningOperationsTest, EcdsaAllCurves) {
     for (auto curve : ValidCurves()) {
+        Digest digest = (curve == EcCurve::CURVE_25519 ? Digest::NONE : Digest::SHA_2_256);
+        SCOPED_TRACE(testing::Message() << "Curve::" << curve);
         ErrorCode error = GenerateKey(AuthorizationSetBuilder()
                                               .Authorization(TAG_NO_AUTH_REQUIRED)
                                               .EcdsaSigningKey(curve)
-                                              .Digest(Digest::SHA_2_256)
+                                              .Digest(digest)
                                               .SetDefaultValidity());
         EXPECT_EQ(ErrorCode::OK, error) << "Failed to generate ECDSA key with curve " << curve;
         if (error != ErrorCode::OK) continue;
 
         string message(1024, 'a');
-        SignMessage(message, AuthorizationSetBuilder().Digest(Digest::SHA_2_256));
+        SignMessage(message, AuthorizationSetBuilder().Digest(digest));
         CheckedDeleteKey();
     }
 }
 
 /*
+ * SigningOperationsTest.EcdsaCurve25519
+ *
+ * Verifies that ECDSA operations succeed with curve25519.
+ */
+TEST_P(SigningOperationsTest, EcdsaCurve25519) {
+    if (!Curve25519Supported()) {
+        GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+    }
+
+    EcCurve curve = EcCurve::CURVE_25519;
+    ErrorCode error = GenerateKey(AuthorizationSetBuilder()
+                                          .Authorization(TAG_NO_AUTH_REQUIRED)
+                                          .EcdsaSigningKey(curve)
+                                          .Digest(Digest::NONE)
+                                          .SetDefaultValidity());
+    ASSERT_EQ(ErrorCode::OK, error) << "Failed to generate ECDSA key with curve " << curve;
+
+    string message(1024, 'a');
+    SignMessage(message, AuthorizationSetBuilder().Digest(Digest::NONE));
+    CheckedDeleteKey();
+}
+
+/*
+ * SigningOperationsTest.EcdsaCurve25519MaxSize
+ *
+ * Verifies that EDDSA operations with curve25519 under the maximum message size succeed.
+ */
+TEST_P(SigningOperationsTest, EcdsaCurve25519MaxSize) {
+    if (!Curve25519Supported()) {
+        GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+    }
+
+    EcCurve curve = EcCurve::CURVE_25519;
+    ErrorCode error = GenerateKey(AuthorizationSetBuilder()
+                                          .Authorization(TAG_NO_AUTH_REQUIRED)
+                                          .EcdsaSigningKey(curve)
+                                          .Digest(Digest::NONE)
+                                          .SetDefaultValidity());
+    ASSERT_EQ(ErrorCode::OK, error) << "Failed to generate ECDSA key with curve " << curve;
+
+    auto params = AuthorizationSetBuilder().Digest(Digest::NONE);
+
+    for (size_t msg_size : {MAX_ED25519_MSG_SIZE - 1, MAX_ED25519_MSG_SIZE}) {
+        SCOPED_TRACE(testing::Message() << "-msg-size=" << msg_size);
+        string message(msg_size, 'a');
+
+        // Attempt to sign via Begin+Finish.
+        AuthorizationSet out_params;
+        ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::SIGN, key_blob_, params, &out_params));
+        EXPECT_TRUE(out_params.empty());
+        string signature;
+        auto result = Finish(message, &signature);
+        EXPECT_EQ(result, ErrorCode::OK);
+        LocalVerifyMessage(message, signature, params);
+
+        // Attempt to sign via Begin+Update+Finish
+        ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::SIGN, key_blob_, params, &out_params));
+        EXPECT_TRUE(out_params.empty());
+        string output;
+        result = Update(message, &output);
+        EXPECT_EQ(result, ErrorCode::OK);
+        EXPECT_EQ(output.size(), 0);
+        string signature2;
+        EXPECT_EQ(ErrorCode::OK, Finish({}, &signature2));
+        LocalVerifyMessage(message, signature2, params);
+    }
+
+    CheckedDeleteKey();
+}
+
+/*
+ * SigningOperationsTest.EcdsaCurve25519MaxSizeFail
+ *
+ * Verifies that EDDSA operations with curve25519 fail when message size is too large.
+ */
+TEST_P(SigningOperationsTest, EcdsaCurve25519MaxSizeFail) {
+    if (!Curve25519Supported()) {
+        GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+    }
+
+    EcCurve curve = EcCurve::CURVE_25519;
+    ErrorCode error = GenerateKey(AuthorizationSetBuilder()
+                                          .Authorization(TAG_NO_AUTH_REQUIRED)
+                                          .EcdsaSigningKey(curve)
+                                          .Digest(Digest::NONE)
+                                          .SetDefaultValidity());
+    ASSERT_EQ(ErrorCode::OK, error) << "Failed to generate ECDSA key with curve " << curve;
+
+    auto params = AuthorizationSetBuilder().Digest(Digest::NONE);
+
+    for (size_t msg_size : {MAX_ED25519_MSG_SIZE + 1, MAX_ED25519_MSG_SIZE * 2}) {
+        SCOPED_TRACE(testing::Message() << "-msg-size=" << msg_size);
+        string message(msg_size, 'a');
+
+        // Attempt to sign via Begin+Finish.
+        AuthorizationSet out_params;
+        ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::SIGN, key_blob_, params, &out_params));
+        EXPECT_TRUE(out_params.empty());
+        string signature;
+        auto result = Finish(message, &signature);
+        EXPECT_EQ(result, ErrorCode::INVALID_INPUT_LENGTH);
+
+        // Attempt to sign via Begin+Update (but never get to Finish)
+        ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::SIGN, key_blob_, params, &out_params));
+        EXPECT_TRUE(out_params.empty());
+        string output;
+        result = Update(message, &output);
+        EXPECT_EQ(result, ErrorCode::INVALID_INPUT_LENGTH);
+    }
+
+    CheckedDeleteKey();
+}
+
+/*
  * SigningOperationsTest.EcdsaNoDigestHugeData
  *
  * Verifies that ECDSA operations support very large messages, even without digesting.  This
@@ -3064,6 +3735,58 @@
     CheckedDeleteKey(&verification_key);
 }
 
+/*
+ * VerificationOperationsTest.HmacVerificationFailsForCorruptSignature
+ *
+ * Verifies HMAC signature verification should fails if message or signature is corrupted.
+ */
+TEST_P(VerificationOperationsTest, HmacVerificationFailsForCorruptSignature) {
+    string key_material = "HelloThisIsAKey";
+
+    vector<uint8_t> signing_key, verification_key;
+    vector<KeyCharacteristics> signing_key_chars, verification_key_chars;
+    EXPECT_EQ(ErrorCode::OK,
+              ImportKey(AuthorizationSetBuilder()
+                                .Authorization(TAG_NO_AUTH_REQUIRED)
+                                .Authorization(TAG_ALGORITHM, Algorithm::HMAC)
+                                .Authorization(TAG_PURPOSE, KeyPurpose::SIGN)
+                                .Digest(Digest::SHA_2_256)
+                                .Authorization(TAG_MIN_MAC_LENGTH, 160),
+                        KeyFormat::RAW, key_material, &signing_key, &signing_key_chars));
+    EXPECT_EQ(ErrorCode::OK,
+              ImportKey(AuthorizationSetBuilder()
+                                .Authorization(TAG_NO_AUTH_REQUIRED)
+                                .Authorization(TAG_ALGORITHM, Algorithm::HMAC)
+                                .Authorization(TAG_PURPOSE, KeyPurpose::VERIFY)
+                                .Digest(Digest::SHA_2_256)
+                                .Authorization(TAG_MIN_MAC_LENGTH, 160),
+                        KeyFormat::RAW, key_material, &verification_key, &verification_key_chars));
+
+    string message = "This is a message.";
+    string signature = SignMessage(
+            signing_key, message,
+            AuthorizationSetBuilder().Digest(Digest::SHA_2_256).Authorization(TAG_MAC_LENGTH, 160));
+
+    AuthorizationSet begin_out_params;
+    ASSERT_EQ(ErrorCode::OK,
+              Begin(KeyPurpose::VERIFY, verification_key,
+                    AuthorizationSetBuilder().Digest(Digest::SHA_2_256), &begin_out_params));
+
+    string corruptMessage = "This is b message.";  // Corrupted message
+    string output;
+    EXPECT_EQ(ErrorCode::VERIFICATION_FAILED, Finish(corruptMessage, signature, &output));
+
+    ASSERT_EQ(ErrorCode::OK,
+              Begin(KeyPurpose::VERIFY, verification_key,
+                    AuthorizationSetBuilder().Digest(Digest::SHA_2_256), &begin_out_params));
+
+    signature[0] += 1;  // Corrupt a signature
+    EXPECT_EQ(ErrorCode::VERIFICATION_FAILED, Finish(message, signature, &output));
+
+    CheckedDeleteKey(&signing_key);
+    CheckedDeleteKey(&verification_key);
+}
+
 INSTANTIATE_KEYMINT_AIDL_TEST(VerificationOperationsTest);
 
 typedef KeyMintAidlTestBase ExportKeyTest;
@@ -3213,6 +3936,33 @@
 }
 
 /*
+ * ImportKeyTest.RsaAttestMultiPurposeFail
+ *
+ * Verifies that importing an RSA key pair with purpose ATTEST_KEY+SIGN fails.
+ */
+TEST_P(ImportKeyTest, RsaAttestMultiPurposeFail) {
+    if (AidlVersion() < 2) {
+        // The KeyMint v1 spec required that KeyPurpose::ATTEST_KEY not be combined
+        // with other key purposes.  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() << "Single-purpose for KeyPurpose::ATTEST_KEY only strict since KeyMint v2";
+    }
+    uint32_t key_size = 2048;
+    string key = rsa_2048_key;
+
+    ASSERT_EQ(ErrorCode::INCOMPATIBLE_PURPOSE,
+              ImportKey(AuthorizationSetBuilder()
+                                .Authorization(TAG_NO_AUTH_REQUIRED)
+                                .RsaSigningKey(key_size, 65537)
+                                .AttestKey()
+                                .Digest(Digest::SHA_2_256)
+                                .Padding(PaddingMode::RSA_PSS)
+                                .SetDefaultValidity(),
+                        KeyFormat::PKCS8, key));
+}
+
+/*
  * ImportKeyTest.EcdsaSuccess
  *
  * Verifies that importing and using an ECDSA P-256 key pair works correctly.
@@ -3294,7 +4044,9 @@
  * Verifies that importing and using an ECDSA P-521 key pair works correctly.
  */
 TEST_P(ImportKeyTest, Ecdsa521Success) {
-    if (SecLevel() == SecurityLevel::STRONGBOX) return;
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        GTEST_SKIP() << "Test not applicable to StrongBox device";
+    }
     ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
                                                .Authorization(TAG_NO_AUTH_REQUIRED)
                                                .EcdsaSigningKey(EcCurve::P_521)
@@ -3329,6 +4081,278 @@
 }
 
 /*
+ * ImportKeyTest.EcdsaAttestMultiPurposeFail
+ *
+ * Verifies that importing and using an ECDSA P-256 key pair with purpose ATTEST_KEY+SIGN fails.
+ */
+TEST_P(ImportKeyTest, EcdsaAttestMultiPurposeFail) {
+    if (AidlVersion() < 2) {
+        // The KeyMint v1 spec required that KeyPurpose::ATTEST_KEY not be combined
+        // with other key purposes.  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() << "Single-purpose for KeyPurpose::ATTEST_KEY only strict since KeyMint v2";
+    }
+    ASSERT_EQ(ErrorCode::INCOMPATIBLE_PURPOSE,
+              ImportKey(AuthorizationSetBuilder()
+                                .Authorization(TAG_NO_AUTH_REQUIRED)
+                                .EcdsaSigningKey(EcCurve::P_256)
+                                .AttestKey()
+                                .Digest(Digest::SHA_2_256)
+                                .SetDefaultValidity(),
+                        KeyFormat::PKCS8, ec_256_key));
+}
+
+/*
+ * ImportKeyTest.Ed25519RawSuccess
+ *
+ * Verifies that importing and using a raw Ed25519 private key works correctly.
+ */
+TEST_P(ImportKeyTest, Ed25519RawSuccess) {
+    if (!Curve25519Supported()) {
+        GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+    }
+
+    ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+                                               .Authorization(TAG_NO_AUTH_REQUIRED)
+                                               .EcdsaSigningKey(EcCurve::CURVE_25519)
+                                               .Digest(Digest::NONE)
+                                               .SetDefaultValidity(),
+                                       KeyFormat::RAW, ed25519_key));
+    CheckCryptoParam(TAG_ALGORITHM, Algorithm::EC);
+    CheckCryptoParam(TAG_EC_CURVE, EcCurve::CURVE_25519);
+    CheckOrigin();
+
+    // The returned cert should hold the correct public key.
+    ASSERT_GT(cert_chain_.size(), 0);
+    X509_Ptr kmKeyCert(parse_cert_blob(cert_chain_[0].encodedCertificate));
+    ASSERT_NE(kmKeyCert, nullptr);
+    EVP_PKEY_Ptr kmPubKey(X509_get_pubkey(kmKeyCert.get()));
+    ASSERT_NE(kmPubKey.get(), nullptr);
+    size_t kmPubKeySize = 32;
+    uint8_t kmPubKeyData[32];
+    ASSERT_EQ(1, EVP_PKEY_get_raw_public_key(kmPubKey.get(), kmPubKeyData, &kmPubKeySize));
+    ASSERT_EQ(kmPubKeySize, 32);
+    EXPECT_EQ(string(kmPubKeyData, kmPubKeyData + 32), ed25519_pubkey);
+
+    string message(32, 'a');
+    auto params = AuthorizationSetBuilder().Digest(Digest::NONE);
+    string signature = SignMessage(message, params);
+    LocalVerifyMessage(message, signature, params);
+}
+
+/*
+ * ImportKeyTest.Ed25519Pkcs8Success
+ *
+ * Verifies that importing and using a PKCS#8-encoded Ed25519 private key works correctly.
+ */
+TEST_P(ImportKeyTest, Ed25519Pkcs8Success) {
+    if (!Curve25519Supported()) {
+        GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+    }
+
+    ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+                                               .Authorization(TAG_NO_AUTH_REQUIRED)
+                                               .EcdsaSigningKey(EcCurve::CURVE_25519)
+                                               .Digest(Digest::NONE)
+                                               .SetDefaultValidity(),
+                                       KeyFormat::PKCS8, ed25519_pkcs8_key));
+    CheckCryptoParam(TAG_ALGORITHM, Algorithm::EC);
+    CheckCryptoParam(TAG_EC_CURVE, EcCurve::CURVE_25519);
+    CheckOrigin();
+
+    // The returned cert should hold the correct public key.
+    ASSERT_GT(cert_chain_.size(), 0);
+    X509_Ptr kmKeyCert(parse_cert_blob(cert_chain_[0].encodedCertificate));
+    ASSERT_NE(kmKeyCert, nullptr);
+    EVP_PKEY_Ptr kmPubKey(X509_get_pubkey(kmKeyCert.get()));
+    ASSERT_NE(kmPubKey.get(), nullptr);
+    size_t kmPubKeySize = 32;
+    uint8_t kmPubKeyData[32];
+    ASSERT_EQ(1, EVP_PKEY_get_raw_public_key(kmPubKey.get(), kmPubKeyData, &kmPubKeySize));
+    ASSERT_EQ(kmPubKeySize, 32);
+    EXPECT_EQ(string(kmPubKeyData, kmPubKeyData + 32), ed25519_pubkey);
+
+    string message(32, 'a');
+    auto params = AuthorizationSetBuilder().Digest(Digest::NONE);
+    string signature = SignMessage(message, params);
+    LocalVerifyMessage(message, signature, params);
+}
+
+/*
+ * ImportKeyTest.Ed25519CurveMismatch
+ *
+ * Verifies that importing an Ed25519 key pair with a curve that doesn't match the key fails in
+ * the correct way.
+ */
+TEST_P(ImportKeyTest, Ed25519CurveMismatch) {
+    if (!Curve25519Supported()) {
+        GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+    }
+
+    ASSERT_NE(ErrorCode::OK,
+              ImportKey(AuthorizationSetBuilder()
+                                .EcdsaSigningKey(EcCurve::P_224 /* Doesn't match key */)
+                                .Digest(Digest::NONE)
+                                .SetDefaultValidity(),
+                        KeyFormat::RAW, ed25519_key));
+}
+
+/*
+ * ImportKeyTest.Ed25519FormatMismatch
+ *
+ * Verifies that importing an Ed25519 key pair with an invalid format fails.
+ */
+TEST_P(ImportKeyTest, Ed25519FormatMismatch) {
+    if (!Curve25519Supported()) {
+        GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+    }
+
+    ASSERT_NE(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+                                               .EcdsaSigningKey(EcCurve::CURVE_25519)
+                                               .Digest(Digest::NONE)
+                                               .SetDefaultValidity(),
+                                       KeyFormat::PKCS8, ed25519_key));
+    ASSERT_NE(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+                                               .EcdsaSigningKey(EcCurve::CURVE_25519)
+                                               .Digest(Digest::NONE)
+                                               .SetDefaultValidity(),
+                                       KeyFormat::RAW, ed25519_pkcs8_key));
+}
+
+/*
+ * ImportKeyTest.Ed25519PurposeMismatch
+ *
+ * Verifies that importing an Ed25519 key pair with an invalid purpose fails.
+ */
+TEST_P(ImportKeyTest, Ed25519PurposeMismatch) {
+    if (!Curve25519Supported()) {
+        GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+    }
+
+    // Can't have both SIGN and ATTEST_KEY
+    ASSERT_NE(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+                                               .EcdsaSigningKey(EcCurve::CURVE_25519)
+                                               .Authorization(TAG_PURPOSE, KeyPurpose::ATTEST_KEY)
+                                               .Digest(Digest::NONE)
+                                               .SetDefaultValidity(),
+                                       KeyFormat::RAW, ed25519_key));
+    // AGREE_KEY is for X25519 (but can only tell the difference if the import key is in
+    // PKCS#8 format and so includes an OID).
+    ASSERT_NE(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+                                               .EcdsaKey(EcCurve::CURVE_25519)
+                                               .Authorization(TAG_PURPOSE, KeyPurpose::AGREE_KEY)
+                                               .Digest(Digest::NONE)
+                                               .SetDefaultValidity(),
+                                       KeyFormat::PKCS8, ed25519_pkcs8_key));
+}
+
+/*
+ * ImportKeyTest.X25519RawSuccess
+ *
+ * Verifies that importing and using a raw X25519 private key works correctly.
+ */
+TEST_P(ImportKeyTest, X25519RawSuccess) {
+    if (!Curve25519Supported()) {
+        GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+    }
+
+    ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+                                               .Authorization(TAG_NO_AUTH_REQUIRED)
+                                               .EcdsaKey(EcCurve::CURVE_25519)
+                                               .Authorization(TAG_PURPOSE, KeyPurpose::AGREE_KEY)
+                                               .SetDefaultValidity(),
+                                       KeyFormat::RAW, x25519_key));
+
+    CheckCryptoParam(TAG_ALGORITHM, Algorithm::EC);
+    CheckCryptoParam(TAG_EC_CURVE, EcCurve::CURVE_25519);
+    CheckOrigin();
+}
+
+/*
+ * ImportKeyTest.X25519Pkcs8Success
+ *
+ * Verifies that importing and using a PKCS#8-encoded X25519 private key works correctly.
+ */
+TEST_P(ImportKeyTest, X25519Pkcs8Success) {
+    if (!Curve25519Supported()) {
+        GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+    }
+
+    ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+                                               .Authorization(TAG_NO_AUTH_REQUIRED)
+                                               .EcdsaKey(EcCurve::CURVE_25519)
+                                               .Authorization(TAG_PURPOSE, KeyPurpose::AGREE_KEY)
+                                               .SetDefaultValidity(),
+                                       KeyFormat::PKCS8, x25519_pkcs8_key));
+
+    CheckCryptoParam(TAG_ALGORITHM, Algorithm::EC);
+    CheckCryptoParam(TAG_EC_CURVE, EcCurve::CURVE_25519);
+    CheckOrigin();
+}
+
+/*
+ * ImportKeyTest.X25519CurveMismatch
+ *
+ * Verifies that importing an X25519 key with a curve that doesn't match the key fails in
+ * the correct way.
+ */
+TEST_P(ImportKeyTest, X25519CurveMismatch) {
+    if (!Curve25519Supported()) {
+        GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+    }
+
+    ASSERT_NE(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+                                               .EcdsaKey(EcCurve::P_224 /* Doesn't match key */)
+                                               .Authorization(TAG_PURPOSE, KeyPurpose::AGREE_KEY)
+                                               .SetDefaultValidity(),
+                                       KeyFormat::RAW, x25519_key));
+}
+
+/*
+ * ImportKeyTest.X25519FormatMismatch
+ *
+ * Verifies that importing an X25519 key with an invalid format fails.
+ */
+TEST_P(ImportKeyTest, X25519FormatMismatch) {
+    if (!Curve25519Supported()) {
+        GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+    }
+
+    ASSERT_NE(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+                                               .EcdsaKey(EcCurve::CURVE_25519)
+                                               .Authorization(TAG_PURPOSE, KeyPurpose::AGREE_KEY)
+                                               .SetDefaultValidity(),
+                                       KeyFormat::PKCS8, x25519_key));
+    ASSERT_NE(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+                                               .EcdsaKey(EcCurve::CURVE_25519)
+                                               .Authorization(TAG_PURPOSE, KeyPurpose::AGREE_KEY)
+                                               .SetDefaultValidity(),
+                                       KeyFormat::RAW, x25519_pkcs8_key));
+}
+
+/*
+ * ImportKeyTest.X25519PurposeMismatch
+ *
+ * Verifies that importing an X25519 key pair with an invalid format fails.
+ */
+TEST_P(ImportKeyTest, X25519PurposeMismatch) {
+    if (!Curve25519Supported()) {
+        GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+    }
+
+    ASSERT_NE(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+                                               .EcdsaKey(EcCurve::CURVE_25519)
+                                               .Authorization(TAG_PURPOSE, KeyPurpose::ATTEST_KEY)
+                                               .SetDefaultValidity(),
+                                       KeyFormat::PKCS8, x25519_pkcs8_key));
+    ASSERT_NE(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+                                               .EcdsaSigningKey(EcCurve::CURVE_25519)
+                                               .SetDefaultValidity(),
+                                       KeyFormat::PKCS8, x25519_pkcs8_key));
+}
+
+/*
  * ImportKeyTest.AesSuccess
  *
  * Verifies that importing and using an AES key works.
@@ -3366,10 +4390,10 @@
     for (uint32_t key_size : {bitlen - 1, bitlen + 1, bitlen - 8, bitlen + 8}) {
         // Explicit key size doesn't match that of the provided key.
         auto result = ImportKey(AuthorizationSetBuilder()
-                                    .Authorization(TAG_NO_AUTH_REQUIRED)
-                                    .AesEncryptionKey(key_size)
-                                    .EcbMode()
-                                    .Padding(PaddingMode::PKCS7),
+                                        .Authorization(TAG_NO_AUTH_REQUIRED)
+                                        .AesEncryptionKey(key_size)
+                                        .EcbMode()
+                                        .Padding(PaddingMode::PKCS7),
                                 KeyFormat::RAW, key);
         ASSERT_TRUE(result == ErrorCode::IMPORT_PARAMETER_MISMATCH ||
                     result == ErrorCode::UNSUPPORTED_KEY_SIZE)
@@ -3433,10 +4457,10 @@
     for (uint32_t key_size : {bitlen - 1, bitlen + 1, bitlen - 8, bitlen + 8}) {
         // Explicit key size doesn't match that of the provided key.
         auto result = ImportKey(AuthorizationSetBuilder()
-                                    .Authorization(TAG_NO_AUTH_REQUIRED)
-                                    .TripleDesEncryptionKey(key_size)
-                                    .EcbMode()
-                                    .Padding(PaddingMode::PKCS7),
+                                        .Authorization(TAG_NO_AUTH_REQUIRED)
+                                        .TripleDesEncryptionKey(key_size)
+                                        .EcbMode()
+                                        .Padding(PaddingMode::PKCS7),
                                 KeyFormat::RAW, key);
         ASSERT_TRUE(result == ErrorCode::IMPORT_PARAMETER_MISMATCH ||
                     result == ErrorCode::UNSUPPORTED_KEY_SIZE)
@@ -3856,7 +4880,7 @@
  * Verifies that raw RSA decryption works.
  */
 TEST_P(EncryptionOperationsTest, RsaNoPaddingSuccess) {
-    for (uint64_t exponent : {3, 65537}) {
+    for (uint64_t exponent : ValidExponents()) {
         ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                                      .Authorization(TAG_NO_AUTH_REQUIRED)
                                                      .RsaEncryptionKey(2048, exponent)
@@ -4003,7 +5027,9 @@
  * with a different digest than was used to encrypt.
  */
 TEST_P(EncryptionOperationsTest, RsaOaepDecryptWithWrongDigest) {
-    if (SecLevel() == SecurityLevel::STRONGBOX) return;
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        GTEST_SKIP() << "Test not applicable to StrongBox device";
+    }
 
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                                  .Authorization(TAG_NO_AUTH_REQUIRED)
@@ -4426,8 +5452,10 @@
     auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
 
     // Try various message lengths; all should work.
-    for (size_t i = 0; i < 32; ++i) {
-        string message(i, 'a');
+    for (size_t i = 0; i <= 48; i++) {
+        SCOPED_TRACE(testing::Message() << "i = " << i);
+        // Edge case: '\t' (0x09) is also a valid PKCS7 padding character.
+        string message(i, '\t');
         string ciphertext = EncryptMessage(message, params);
         EXPECT_EQ(i + 16 - (i % 16), ciphertext.size());
         string plaintext = DecryptMessage(ciphertext, params);
@@ -4451,7 +5479,7 @@
     auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
 
     // Try various message lengths; all should fail
-    for (size_t i = 0; i < 32; ++i) {
+    for (size_t i = 0; i <= 48; i++) {
         string message(i, 'a');
         EXPECT_EQ(ErrorCode::INCOMPATIBLE_PADDING_MODE, Begin(KeyPurpose::ENCRYPT, params));
     }
@@ -4475,11 +5503,49 @@
     string ciphertext = EncryptMessage(message, params);
     EXPECT_EQ(16U, ciphertext.size());
     EXPECT_NE(ciphertext, message);
-    ++ciphertext[ciphertext.size() / 2];
 
+    for (size_t i = 0; i < kMaxPaddingCorruptionRetries; ++i) {
+        ++ciphertext[ciphertext.size() / 2];
+
+        EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params));
+        string plaintext;
+        ErrorCode error = Finish(ciphertext, &plaintext);
+        if (error == ErrorCode::INVALID_ARGUMENT) {
+            // This is the expected error, we can exit the test now.
+            return;
+        } else {
+            // Very small chance we got valid decryption, so try again.
+            ASSERT_EQ(error, ErrorCode::OK)
+                    << "Expected INVALID_ARGUMENT or (rarely) OK, got " << error;
+        }
+    }
+    FAIL() << "Corrupt ciphertext should have failed to decrypt by now.";
+}
+
+/*
+ * EncryptionOperationsTest.AesEcbPkcs7CiphertextTooShort
+ *
+ * Verifies that AES decryption fails in the correct way when the padding is corrupted.
+ */
+TEST_P(EncryptionOperationsTest, AesEcbPkcs7CiphertextTooShort) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                                 .Authorization(TAG_NO_AUTH_REQUIRED)
+                                                 .AesEncryptionKey(128)
+                                                 .Authorization(TAG_BLOCK_MODE, BlockMode::ECB)
+                                                 .Padding(PaddingMode::PKCS7)));
+
+    auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
+
+    string message = "a";
+    string ciphertext = EncryptMessage(message, params);
+    EXPECT_EQ(16U, ciphertext.size());
+    EXPECT_NE(ciphertext, message);
+
+    // Shorten the ciphertext.
+    ciphertext.resize(ciphertext.size() - 1);
     EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params));
     string plaintext;
-    EXPECT_EQ(ErrorCode::INVALID_INPUT_LENGTH, Finish(message, &plaintext));
+    EXPECT_EQ(ErrorCode::INVALID_INPUT_LENGTH, Finish(ciphertext, &plaintext));
 }
 
 vector<uint8_t> CopyIv(const AuthorizationSet& set) {
@@ -4536,89 +5602,39 @@
 }
 
 /*
- * EncryptionOperationsTest.AesIncremental
+ * EncryptionOperationsTest.AesEcbIncremental
  *
- * Verifies that AES works, all modes, when provided data in various size increments.
+ * Verifies that AES works for ECB block mode, when provided data in various size increments.
  */
-TEST_P(EncryptionOperationsTest, AesIncremental) {
-    auto block_modes = {
-            BlockMode::ECB,
-            BlockMode::CBC,
-            BlockMode::CTR,
-            BlockMode::GCM,
-    };
+TEST_P(EncryptionOperationsTest, AesEcbIncremental) {
+    CheckAesIncrementalEncryptOperation(BlockMode::ECB, 240);
+}
 
-    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                                 .Authorization(TAG_NO_AUTH_REQUIRED)
-                                                 .AesEncryptionKey(128)
-                                                 .BlockMode(block_modes)
-                                                 .Padding(PaddingMode::NONE)
-                                                 .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+/*
+ * EncryptionOperationsTest.AesCbcIncremental
+ *
+ * Verifies that AES works for CBC block mode, when provided data in various size increments.
+ */
+TEST_P(EncryptionOperationsTest, AesCbcIncremental) {
+    CheckAesIncrementalEncryptOperation(BlockMode::CBC, 240);
+}
 
-    for (int increment = 1; increment <= 240; ++increment) {
-        for (auto block_mode : block_modes) {
-            string message(240, 'a');
-            auto params =
-                    AuthorizationSetBuilder().BlockMode(block_mode).Padding(PaddingMode::NONE);
-            if (block_mode == BlockMode::GCM) {
-                params.Authorization(TAG_MAC_LENGTH, 128) /* for GCM */;
-            }
+/*
+ * EncryptionOperationsTest.AesCtrIncremental
+ *
+ * Verifies that AES works for CTR block mode, when provided data in various size increments.
+ */
+TEST_P(EncryptionOperationsTest, AesCtrIncremental) {
+    CheckAesIncrementalEncryptOperation(BlockMode::CTR, 240);
+}
 
-            AuthorizationSet output_params;
-            EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params, &output_params));
-
-            string ciphertext;
-            string to_send;
-            for (size_t i = 0; i < message.size(); i += increment) {
-                EXPECT_EQ(ErrorCode::OK, Update(message.substr(i, increment), &ciphertext));
-            }
-            EXPECT_EQ(ErrorCode::OK, Finish(to_send, &ciphertext))
-                    << "Error sending " << to_send << " with block mode " << block_mode;
-
-            switch (block_mode) {
-                case BlockMode::GCM:
-                    EXPECT_EQ(message.size() + 16, ciphertext.size());
-                    break;
-                case BlockMode::CTR:
-                    EXPECT_EQ(message.size(), ciphertext.size());
-                    break;
-                case BlockMode::CBC:
-                case BlockMode::ECB:
-                    EXPECT_EQ(message.size() + message.size() % 16, ciphertext.size());
-                    break;
-            }
-
-            auto iv = output_params.GetTagValue(TAG_NONCE);
-            switch (block_mode) {
-                case BlockMode::CBC:
-                case BlockMode::GCM:
-                case BlockMode::CTR:
-                    ASSERT_TRUE(iv) << "No IV for block mode " << block_mode;
-                    EXPECT_EQ(block_mode == BlockMode::GCM ? 12U : 16U, iv->get().size());
-                    params.push_back(TAG_NONCE, iv->get());
-                    break;
-
-                case BlockMode::ECB:
-                    EXPECT_FALSE(iv) << "ECB mode should not generate IV";
-                    break;
-            }
-
-            EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params))
-                    << "Decrypt begin() failed for block mode " << block_mode;
-
-            string plaintext;
-            for (size_t i = 0; i < ciphertext.size(); i += increment) {
-                EXPECT_EQ(ErrorCode::OK, Update(ciphertext.substr(i, increment), &plaintext));
-            }
-            ErrorCode error = Finish(to_send, &plaintext);
-            ASSERT_EQ(ErrorCode::OK, error) << "Decryption failed for block mode " << block_mode
-                                            << " and increment " << increment;
-            if (error == ErrorCode::OK) {
-                ASSERT_EQ(message, plaintext) << "Decryption didn't match for block mode "
-                                              << block_mode << " and increment " << increment;
-            }
-        }
-    }
+/*
+ * EncryptionOperationsTest.AesGcmIncremental
+ *
+ * Verifies that AES works for GCM block mode, when provided data in various size increments.
+ */
+TEST_P(EncryptionOperationsTest, AesGcmIncremental) {
+    CheckAesIncrementalEncryptOperation(BlockMode::GCM, 240);
 }
 
 struct AesCtrSp80038aTestVector {
@@ -4761,6 +5777,49 @@
 }
 
 /*
+ * EncryptionOperationsTest.AesCbcZeroInputSuccessb
+ *
+ * Verifies that keymaster generates correct output on zero-input with
+ * NonePadding mode
+ */
+TEST_P(EncryptionOperationsTest, AesCbcZeroInputSuccess) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                                 .Authorization(TAG_NO_AUTH_REQUIRED)
+                                                 .AesEncryptionKey(128)
+                                                 .BlockMode(BlockMode::CBC)
+                                                 .Padding(PaddingMode::NONE, PaddingMode::PKCS7)));
+
+    // Zero input message
+    string message = "";
+    for (auto padding : {PaddingMode::NONE, PaddingMode::PKCS7}) {
+        auto params = AuthorizationSetBuilder().BlockMode(BlockMode::CBC).Padding(padding);
+        AuthorizationSet out_params;
+        string ciphertext1 = EncryptMessage(message, params, &out_params);
+        vector<uint8_t> iv1 = CopyIv(out_params);
+        if (padding == PaddingMode::NONE)
+            EXPECT_EQ(message.size(), ciphertext1.size()) << "PaddingMode: " << padding;
+        else
+            EXPECT_EQ(message.size(), ciphertext1.size() - 16) << "PaddingMode: " << padding;
+
+        out_params.Clear();
+
+        string ciphertext2 = EncryptMessage(message, params, &out_params);
+        vector<uint8_t> iv2 = CopyIv(out_params);
+        if (padding == PaddingMode::NONE)
+            EXPECT_EQ(message.size(), ciphertext2.size()) << "PaddingMode: " << padding;
+        else
+            EXPECT_EQ(message.size(), ciphertext2.size() - 16) << "PaddingMode: " << padding;
+
+        // IVs should be random
+        EXPECT_NE(iv1, iv2) << "PaddingMode: " << padding;
+
+        params.push_back(TAG_NONCE, iv1);
+        string plaintext = DecryptMessage(ciphertext1, params);
+        EXPECT_EQ(message, plaintext) << "PaddingMode: " << padding;
+    }
+}
+
+/*
  * EncryptionOperationsTest.AesCallerNonce
  *
  * Verifies that AES caller-provided nonces work correctly.
@@ -5127,7 +6186,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));
@@ -5170,7 +6229,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"));
@@ -5186,7 +6245,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));
@@ -5213,7 +6272,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;
@@ -5247,7 +6306,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));
@@ -5256,7 +6315,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));
@@ -5283,7 +6342,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;
@@ -5293,7 +6352,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));
@@ -5325,7 +6384,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));
@@ -5337,7 +6396,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));
@@ -5442,15 +6501,27 @@
     string ciphertext = EncryptMessage(message, BlockMode::ECB, PaddingMode::PKCS7);
     EXPECT_EQ(8U, ciphertext.size());
     EXPECT_NE(ciphertext, message);
-    ++ciphertext[ciphertext.size() / 2];
 
     AuthorizationSetBuilder begin_params;
     begin_params.push_back(TAG_BLOCK_MODE, BlockMode::ECB);
     begin_params.push_back(TAG_PADDING, PaddingMode::PKCS7);
-    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params));
-    string plaintext;
-    EXPECT_EQ(ErrorCode::OK, Update(ciphertext, &plaintext));
-    EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, Finish(&plaintext));
+
+    for (size_t i = 0; i < kMaxPaddingCorruptionRetries; ++i) {
+        ++ciphertext[ciphertext.size() / 2];
+
+        ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params));
+        string plaintext;
+        EXPECT_EQ(ErrorCode::OK, Update(ciphertext, &plaintext));
+        ErrorCode error = Finish(&plaintext);
+        if (error == ErrorCode::INVALID_ARGUMENT) {
+            // This is the expected error, we can exit the test now.
+            return;
+        } else {
+            // Very small chance we got valid decryption, so try again.
+            ASSERT_EQ(error, ErrorCode::OK);
+        }
+    }
+    FAIL() << "Corrupt ciphertext should have failed to decrypt by now.";
 }
 
 struct TripleDesTestVector {
@@ -5570,8 +6641,8 @@
 
     ASSERT_GT(key_blob_.size(), 0U);
 
-    // Two-block message.
-    string message = "1234567890123456";
+    // Four-block message.
+    string message = "12345678901234561234567890123456";
     vector<uint8_t> iv1;
     string ciphertext1 = EncryptMessage(message, BlockMode::CBC, PaddingMode::NONE, &iv1);
     EXPECT_EQ(message.size(), ciphertext1.size());
@@ -5710,7 +6781,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));
 
@@ -5731,8 +6802,10 @@
                                                  .Padding(PaddingMode::PKCS7)));
 
     // Try various message lengths; all should work.
-    for (size_t i = 0; i < 32; ++i) {
-        string message(i, 'a');
+    for (size_t i = 0; i <= 32; i++) {
+        SCOPED_TRACE(testing::Message() << "i = " << i);
+        // Edge case: '\t' (0x09) is also a valid PKCS7 padding character, albeit not for 3DES.
+        string message(i, '\t');
         vector<uint8_t> iv;
         string ciphertext = EncryptMessage(message, BlockMode::CBC, PaddingMode::PKCS7, &iv);
         EXPECT_EQ(i + 8 - (i % 8), ciphertext.size());
@@ -5754,7 +6827,7 @@
                                                  .Padding(PaddingMode::NONE)));
 
     // Try various message lengths; all should fail.
-    for (size_t i = 0; i < 32; ++i) {
+    for (size_t i = 0; i <= 32; i++) {
         auto begin_params =
                 AuthorizationSetBuilder().BlockMode(BlockMode::CBC).Padding(PaddingMode::PKCS7);
         EXPECT_EQ(ErrorCode::INCOMPATIBLE_PADDING_MODE, Begin(KeyPurpose::ENCRYPT, begin_params));
@@ -5778,16 +6851,28 @@
     string ciphertext = EncryptMessage(message, BlockMode::CBC, PaddingMode::PKCS7, &iv);
     EXPECT_EQ(8U, ciphertext.size());
     EXPECT_NE(ciphertext, message);
-    ++ciphertext[ciphertext.size() / 2];
 
     auto begin_params = AuthorizationSetBuilder()
                                 .BlockMode(BlockMode::CBC)
                                 .Padding(PaddingMode::PKCS7)
                                 .Authorization(TAG_NONCE, iv);
-    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params));
-    string plaintext;
-    EXPECT_EQ(ErrorCode::OK, Update(ciphertext, &plaintext));
-    EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, Finish(&plaintext));
+
+    for (size_t i = 0; i < kMaxPaddingCorruptionRetries; ++i) {
+        SCOPED_TRACE(testing::Message() << "i = " << i);
+        ++ciphertext[ciphertext.size() / 2];
+        ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params));
+        string plaintext;
+        EXPECT_EQ(ErrorCode::OK, Update(ciphertext, &plaintext));
+        ErrorCode error = Finish(&plaintext);
+        if (error == ErrorCode::INVALID_ARGUMENT) {
+            // This is the expected error, we can exit the test now.
+            return;
+        } else {
+            // Very small chance we got valid decryption, so try again.
+            ASSERT_EQ(error, ErrorCode::OK);
+        }
+    }
+    FAIL() << "Corrupt ciphertext should have failed to decrypt by now.";
 }
 
 /*
@@ -5807,7 +6892,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)
@@ -5821,7 +6906,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));
@@ -5840,7 +6925,9 @@
  * Verifies that the max uses per boot tag works correctly with AES keys.
  */
 TEST_P(MaxOperationsTest, TestLimitAes) {
-    if (SecLevel() == SecurityLevel::STRONGBOX) return;
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        GTEST_SKIP() << "Test not applicable to StrongBox device";
+    }
 
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                                  .Authorization(TAG_NO_AUTH_REQUIRED)
@@ -5867,7 +6954,9 @@
  * Verifies that the max uses per boot tag works correctly with RSA keys.
  */
 TEST_P(MaxOperationsTest, TestLimitRsa) {
-    if (SecLevel() == SecurityLevel::STRONGBOX) return;
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        GTEST_SKIP() << "Test not applicable to StrongBox device";
+    }
 
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                                  .Authorization(TAG_NO_AUTH_REQUIRED)
@@ -5898,7 +6987,9 @@
  * Verifies that the usage count limit tag = 1 works correctly with AES keys.
  */
 TEST_P(UsageCountLimitTest, TestSingleUseAes) {
-    if (SecLevel() == SecurityLevel::STRONGBOX) return;
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        GTEST_SKIP() << "Test not applicable to StrongBox device";
+    }
 
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                                  .Authorization(TAG_NO_AUTH_REQUIRED)
@@ -5932,7 +7023,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));
     }
 }
 
@@ -5942,7 +7033,9 @@
  * Verifies that the usage count limit tag > 1 works correctly with AES keys.
  */
 TEST_P(UsageCountLimitTest, TestLimitedUseAes) {
-    if (SecLevel() == SecurityLevel::STRONGBOX) return;
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        GTEST_SKIP() << "Test not applicable to StrongBox device";
+    }
 
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                                  .Authorization(TAG_NO_AUTH_REQUIRED)
@@ -5977,7 +7070,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));
     }
 }
 
@@ -5987,7 +7080,9 @@
  * Verifies that the usage count limit tag = 1 works correctly with RSA keys.
  */
 TEST_P(UsageCountLimitTest, TestSingleUseRsa) {
-    if (SecLevel() == SecurityLevel::STRONGBOX) return;
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        GTEST_SKIP() << "Test not applicable to StrongBox device";
+    }
 
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                                  .Authorization(TAG_NO_AUTH_REQUIRED)
@@ -6021,7 +7116,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));
     }
 }
 
@@ -6031,7 +7126,9 @@
  * Verifies that the usage count limit tag > 1 works correctly with RSA keys.
  */
 TEST_P(UsageCountLimitTest, TestLimitUseRsa) {
-    if (SecLevel() == SecurityLevel::STRONGBOX) return;
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        GTEST_SKIP() << "Test not applicable to StrongBox device";
+    }
 
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                                  .Authorization(TAG_NO_AUTH_REQUIRED)
@@ -6066,7 +7163,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));
     }
 }
 
@@ -6078,7 +7175,9 @@
  * in hardware.
  */
 TEST_P(UsageCountLimitTest, TestSingleUseKeyAndRollbackResistance) {
-    if (SecLevel() == SecurityLevel::STRONGBOX) return;
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        GTEST_SKIP() << "Test not applicable to StrongBox device";
+    }
 
     auto error = GenerateKey(AuthorizationSetBuilder()
                                      .RsaSigningKey(2048, 65537)
@@ -6087,38 +7186,39 @@
                                      .Authorization(TAG_NO_AUTH_REQUIRED)
                                      .Authorization(TAG_ROLLBACK_RESISTANCE)
                                      .SetDefaultValidity());
-    ASSERT_TRUE(error == ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE || error == ErrorCode::OK);
-
-    if (error == ErrorCode::OK) {
-        // Rollback resistance is supported by KeyMint, verify it is enforced in hardware.
-        AuthorizationSet hardwareEnforced(SecLevelAuthorizations());
-        ASSERT_TRUE(hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE));
-        ASSERT_EQ(ErrorCode::OK, DeleteKey());
-
-        // The KeyMint should also enforce single use key in hardware when it supports rollback
-        // resistance.
-        ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                                     .Authorization(TAG_NO_AUTH_REQUIRED)
-                                                     .RsaSigningKey(1024, 65537)
-                                                     .NoDigestOrPadding()
-                                                     .Authorization(TAG_USAGE_COUNT_LIMIT, 1)
-                                                     .SetDefaultValidity()));
-
-        // Check the usage count limit tag appears in the hardware authorizations.
-        AuthorizationSet hardware_auths = HwEnforcedAuthorizations(key_characteristics_);
-        EXPECT_TRUE(hardware_auths.Contains(TAG_USAGE_COUNT_LIMIT, 1U))
-                << "key usage count limit " << 1U << " missing";
-
-        string message = "1234567890123456";
-        auto params = AuthorizationSetBuilder().NoDigestOrPadding();
-
-        // First usage of RSA key should work.
-        SignMessage(message, params);
-
-        // Usage count limit tag is enforced by hardware. After using the key, the key blob
-        // must be invalidated from secure storage (such as RPMB partition).
-        EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB, Begin(KeyPurpose::SIGN, params));
+    if (error == ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE) {
+        GTEST_SKIP() << "Rollback resistance not supported";
     }
+
+    // Rollback resistance is supported by KeyMint, verify it is enforced in hardware.
+    ASSERT_EQ(ErrorCode::OK, error);
+    AuthorizationSet hardwareEnforced(SecLevelAuthorizations());
+    ASSERT_TRUE(hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE));
+    ASSERT_EQ(ErrorCode::OK, DeleteKey());
+
+    // The KeyMint should also enforce single use key in hardware when it supports rollback
+    // resistance.
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                                 .Authorization(TAG_NO_AUTH_REQUIRED)
+                                                 .RsaSigningKey(1024, 65537)
+                                                 .NoDigestOrPadding()
+                                                 .Authorization(TAG_USAGE_COUNT_LIMIT, 1)
+                                                 .SetDefaultValidity()));
+
+    // Check the usage count limit tag appears in the hardware authorizations.
+    AuthorizationSet hardware_auths = HwEnforcedAuthorizations(key_characteristics_);
+    EXPECT_TRUE(hardware_auths.Contains(TAG_USAGE_COUNT_LIMIT, 1U))
+            << "key usage count limit " << 1U << " missing";
+
+    string message = "1234567890123456";
+    auto params = AuthorizationSetBuilder().NoDigestOrPadding();
+
+    // First usage of RSA key should work.
+    SignMessage(message, params);
+
+    // Usage count limit tag is enforced by hardware. After using the key, the key blob
+    // must be invalidated from secure storage (such as RPMB partition).
+    EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB, Begin(KeyPurpose::SIGN, params));
 }
 
 INSTANTIATE_KEYMINT_AIDL_TEST(UsageCountLimitTest);
@@ -6195,24 +7295,25 @@
                                      .Authorization(TAG_NO_AUTH_REQUIRED)
                                      .Authorization(TAG_ROLLBACK_RESISTANCE)
                                      .SetDefaultValidity());
-    ASSERT_TRUE(error == ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE || error == ErrorCode::OK);
+    if (error == ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE) {
+        GTEST_SKIP() << "Rollback resistance not supported";
+    }
 
     // Delete must work if rollback protection is implemented
-    if (error == ErrorCode::OK) {
-        AuthorizationSet hardwareEnforced(SecLevelAuthorizations());
-        ASSERT_TRUE(hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE));
+    ASSERT_EQ(ErrorCode::OK, error);
+    AuthorizationSet hardwareEnforced(SecLevelAuthorizations());
+    ASSERT_TRUE(hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE));
 
-        ASSERT_EQ(ErrorCode::OK, DeleteKey(true /* keep key blob */));
+    ASSERT_EQ(ErrorCode::OK, DeleteKey(true /* keep key blob */));
 
-        string message = "12345678901234567890123456789012";
-        AuthorizationSet begin_out_params;
-        EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
-                  Begin(KeyPurpose::SIGN, key_blob_,
-                        AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE),
-                        &begin_out_params));
-        AbortIfNeeded();
-        key_blob_ = AidlBuf();
-    }
+    string message = "12345678901234567890123456789012";
+    AuthorizationSet begin_out_params;
+    EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
+              Begin(KeyPurpose::SIGN, key_blob_,
+                    AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE),
+                    &begin_out_params));
+    AbortIfNeeded();
+    key_blob_ = AidlBuf();
 }
 
 /**
@@ -6229,21 +7330,22 @@
                                      .Authorization(TAG_NO_AUTH_REQUIRED)
                                      .Authorization(TAG_ROLLBACK_RESISTANCE)
                                      .SetDefaultValidity());
-    ASSERT_TRUE(error == ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE || error == ErrorCode::OK);
+    if (error == ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE) {
+        GTEST_SKIP() << "Rollback resistance not supported";
+    }
 
     // Delete must work if rollback protection is implemented
-    if (error == ErrorCode::OK) {
-        AuthorizationSet enforced(SecLevelAuthorizations());
-        ASSERT_TRUE(enforced.Contains(TAG_ROLLBACK_RESISTANCE));
+    ASSERT_EQ(ErrorCode::OK, error);
+    AuthorizationSet enforced(SecLevelAuthorizations());
+    ASSERT_TRUE(enforced.Contains(TAG_ROLLBACK_RESISTANCE));
 
-        // Delete the key we don't care about the result at this point.
-        DeleteKey();
+    // Delete the key we don't care about the result at this point.
+    DeleteKey();
 
-        // Now create an invalid key blob and delete it.
-        key_blob_ = AidlBuf("just some garbage data which is not a valid key blob");
+    // Now create an invalid key blob and delete it.
+    key_blob_ = AidlBuf("just some garbage data which is not a valid key blob");
 
-        ASSERT_EQ(ErrorCode::OK, DeleteKey());
-    }
+    ASSERT_EQ(ErrorCode::OK, DeleteKey());
 }
 
 /**
@@ -6258,32 +7360,37 @@
  * credentials stored in Keystore/Keymint.
  */
 TEST_P(KeyDeletionTest, DeleteAllKeys) {
-    if (!arm_deleteAllKeys) return;
+    if (!arm_deleteAllKeys) {
+        GTEST_SKIP() << "Option --arm_deleteAllKeys not set";
+        return;
+    }
     auto error = GenerateKey(AuthorizationSetBuilder()
                                      .RsaSigningKey(2048, 65537)
                                      .Digest(Digest::NONE)
                                      .Padding(PaddingMode::NONE)
                                      .Authorization(TAG_NO_AUTH_REQUIRED)
-                                     .Authorization(TAG_ROLLBACK_RESISTANCE));
-    ASSERT_TRUE(error == ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE || error == ErrorCode::OK);
+                                     .Authorization(TAG_ROLLBACK_RESISTANCE)
+                                     .SetDefaultValidity());
+    if (error == ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE) {
+        GTEST_SKIP() << "Rollback resistance not supported";
+    }
 
     // Delete must work if rollback protection is implemented
-    if (error == ErrorCode::OK) {
-        AuthorizationSet hardwareEnforced(SecLevelAuthorizations());
-        ASSERT_TRUE(hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE));
+    ASSERT_EQ(ErrorCode::OK, error);
+    AuthorizationSet hardwareEnforced(SecLevelAuthorizations());
+    ASSERT_TRUE(hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE));
 
-        ASSERT_EQ(ErrorCode::OK, DeleteAllKeys());
+    ASSERT_EQ(ErrorCode::OK, DeleteAllKeys());
 
-        string message = "12345678901234567890123456789012";
-        AuthorizationSet begin_out_params;
+    string message = "12345678901234567890123456789012";
+    AuthorizationSet begin_out_params;
 
-        EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
-                  Begin(KeyPurpose::SIGN, key_blob_,
-                        AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE),
-                        &begin_out_params));
-        AbortIfNeeded();
-        key_blob_ = AidlBuf();
-    }
+    EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
+              Begin(KeyPurpose::SIGN, key_blob_,
+                    AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE),
+                    &begin_out_params));
+    AbortIfNeeded();
+    key_blob_ = AidlBuf();
 }
 
 INSTANTIATE_KEYMINT_AIDL_TEST(KeyDeletionTest);
@@ -6356,7 +7463,7 @@
     size_t i;
 
     for (i = 0; i < max_operations; i++) {
-        result = Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params, op_handles[i]);
+        result = Begin(KeyPurpose::DECRYPT, key_blob_, params, &out_params, op_handles[i]);
         if (ErrorCode::OK != result) {
             break;
         }
@@ -6364,12 +7471,12 @@
     EXPECT_EQ(ErrorCode::TOO_MANY_OPERATIONS, result);
     // Try again just in case there's a weird overflow bug
     EXPECT_EQ(ErrorCode::TOO_MANY_OPERATIONS,
-              Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params));
+              Begin(KeyPurpose::DECRYPT, key_blob_, params, &out_params));
     for (size_t j = 0; j < i; j++) {
         EXPECT_EQ(ErrorCode::OK, Abort(op_handles[j]))
                 << "Aboort failed for i = " << j << std::endl;
     }
-    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params));
+    ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, key_blob_, params, &out_params));
     AbortIfNeeded();
 }
 
@@ -6394,7 +7501,7 @@
                 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;
@@ -6405,7 +7512,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);
@@ -6417,9 +7524,7 @@
 
 INSTANTIATE_KEYMINT_AIDL_TEST(TransportLimitTest);
 
-typedef KeyMintAidlTestBase KeyAgreementTest;
-
-int CurveToOpenSslCurveName(EcCurve curve) {
+static int EcdhCurveToOpenSslCurveName(EcCurve curve) {
     switch (curve) {
         case EcCurve::P_224:
             return NID_secp224r1;
@@ -6429,13 +7534,122 @@
             return NID_secp384r1;
         case EcCurve::P_521:
             return NID_secp521r1;
+        case EcCurve::CURVE_25519:
+            return NID_X25519;
     }
 }
 
+class KeyAgreementTest : public KeyMintAidlTestBase {
+  protected:
+    void GenerateLocalEcKey(EcCurve localCurve, EVP_PKEY_Ptr* localPrivKey,
+                            std::vector<uint8_t>* localPublicKey) {
+        // Generate EC key locally (with access to private key material)
+        if (localCurve == EcCurve::CURVE_25519) {
+            uint8_t privKeyData[32];
+            uint8_t pubKeyData[32];
+            X25519_keypair(pubKeyData, privKeyData);
+            *localPrivKey = EVP_PKEY_Ptr(EVP_PKEY_new_raw_private_key(
+                    EVP_PKEY_X25519, nullptr, privKeyData, sizeof(privKeyData)));
+        } else {
+            auto ecKey = EC_KEY_Ptr(EC_KEY_new());
+            int curveName = EcdhCurveToOpenSslCurveName(localCurve);
+            auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(curveName));
+            ASSERT_NE(group, nullptr);
+            ASSERT_EQ(EC_KEY_set_group(ecKey.get(), group.get()), 1);
+            ASSERT_EQ(EC_KEY_generate_key(ecKey.get()), 1);
+            *localPrivKey = EVP_PKEY_Ptr(EVP_PKEY_new());
+            ASSERT_EQ(EVP_PKEY_set1_EC_KEY(localPrivKey->get(), ecKey.get()), 1);
+        }
+
+        // Get encoded form of the public part of the locally generated key...
+        unsigned char* p = nullptr;
+        int localPublicKeySize = i2d_PUBKEY(localPrivKey->get(), &p);
+        ASSERT_GT(localPublicKeySize, 0);
+        *localPublicKey = vector<uint8_t>(reinterpret_cast<const uint8_t*>(p),
+                                          reinterpret_cast<const uint8_t*>(p + localPublicKeySize));
+        OPENSSL_free(p);
+    }
+
+    void GenerateKeyMintEcKey(EcCurve curve, EVP_PKEY_Ptr* kmPubKey) {
+        vector<uint8_t> challenge = {0x41, 0x42};
+        auto builder = AuthorizationSetBuilder()
+                               .Authorization(TAG_NO_AUTH_REQUIRED)
+                               .Authorization(TAG_EC_CURVE, curve)
+                               .Authorization(TAG_PURPOSE, KeyPurpose::AGREE_KEY)
+                               .Authorization(TAG_ALGORITHM, Algorithm::EC)
+                               .Authorization(TAG_ATTESTATION_APPLICATION_ID, {0x61, 0x62})
+                               .Authorization(TAG_ATTESTATION_CHALLENGE, challenge)
+                               .SetDefaultValidity();
+        ErrorCode result = GenerateKey(builder);
+
+        if (SecLevel() == SecurityLevel::STRONGBOX) {
+            if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) {
+                result = GenerateKeyWithSelfSignedAttestKey(
+                        AuthorizationSetBuilder()
+                                .EcdsaKey(EcCurve::P_256)
+                                .AttestKey()
+                                .SetDefaultValidity(), /* attest key params */
+                        builder, &key_blob_, &key_characteristics_, &cert_chain_);
+            }
+        }
+        ASSERT_EQ(ErrorCode::OK, result) << "Failed to generate key";
+        ASSERT_GT(cert_chain_.size(), 0);
+        X509_Ptr kmKeyCert(parse_cert_blob(cert_chain_[0].encodedCertificate));
+        ASSERT_NE(kmKeyCert, nullptr);
+        // Check that keyAgreement (bit 4) is set in KeyUsage
+        EXPECT_TRUE((X509_get_key_usage(kmKeyCert.get()) & X509v3_KU_KEY_AGREEMENT) != 0);
+        *kmPubKey = EVP_PKEY_Ptr(X509_get_pubkey(kmKeyCert.get()));
+        ASSERT_NE(*kmPubKey, nullptr);
+        if (dump_Attestations) {
+            for (size_t n = 0; n < cert_chain_.size(); n++) {
+                std::cout << bin2hex(cert_chain_[n].encodedCertificate) << std::endl;
+            }
+        }
+    }
+
+    void CheckAgreement(EVP_PKEY_Ptr kmPubKey, EVP_PKEY_Ptr localPrivKey,
+                        const std::vector<uint8_t>& localPublicKey) {
+        ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::AGREE_KEY, AuthorizationSetBuilder()));
+        string ZabFromKeyMintStr;
+        ASSERT_EQ(ErrorCode::OK,
+                  Finish(string(localPublicKey.begin(), localPublicKey.end()), &ZabFromKeyMintStr));
+        vector<uint8_t> ZabFromKeyMint(ZabFromKeyMintStr.begin(), ZabFromKeyMintStr.end());
+        vector<uint8_t> ZabFromTest;
+
+        if (EVP_PKEY_id(kmPubKey.get()) == EVP_PKEY_X25519) {
+            size_t kmPubKeySize = 32;
+            uint8_t kmPubKeyData[32];
+            ASSERT_EQ(1, EVP_PKEY_get_raw_public_key(kmPubKey.get(), kmPubKeyData, &kmPubKeySize));
+            ASSERT_EQ(kmPubKeySize, 32);
+
+            uint8_t localPrivKeyData[32];
+            size_t localPrivKeySize = 32;
+            ASSERT_EQ(1, EVP_PKEY_get_raw_private_key(localPrivKey.get(), localPrivKeyData,
+                                                      &localPrivKeySize));
+            ASSERT_EQ(localPrivKeySize, 32);
+
+            uint8_t sharedKey[32];
+            ASSERT_EQ(1, X25519(sharedKey, localPrivKeyData, kmPubKeyData));
+            ZabFromTest = std::vector<uint8_t>(sharedKey, sharedKey + 32);
+        } else {
+            // Perform local ECDH between the two keys so we can check if we get the same Zab..
+            auto ctx = EVP_PKEY_CTX_Ptr(EVP_PKEY_CTX_new(localPrivKey.get(), nullptr));
+            ASSERT_NE(ctx, nullptr);
+            ASSERT_EQ(EVP_PKEY_derive_init(ctx.get()), 1);
+            ASSERT_EQ(EVP_PKEY_derive_set_peer(ctx.get(), kmPubKey.get()), 1);
+            size_t ZabFromTestLen = 0;
+            ASSERT_EQ(EVP_PKEY_derive(ctx.get(), nullptr, &ZabFromTestLen), 1);
+            ZabFromTest.resize(ZabFromTestLen);
+            ASSERT_EQ(EVP_PKEY_derive(ctx.get(), ZabFromTest.data(), &ZabFromTestLen), 1);
+        }
+        EXPECT_EQ(ZabFromKeyMint, ZabFromTest);
+    }
+};
+
 /*
  * KeyAgreementTest.Ecdh
  *
- * Verifies that ECDH works for all curves
+ * Verifies that ECDH works for all required curves
  */
 TEST_P(KeyAgreementTest, Ecdh) {
     // Because it's possible to use this API with keys on different curves, we
@@ -6448,82 +7662,31 @@
     //
     for (auto curve : ValidCurves()) {
         for (auto localCurve : ValidCurves()) {
-            // Generate EC key locally (with access to private key material)
-            auto ecKey = EC_KEY_Ptr(EC_KEY_new());
-            int curveName = CurveToOpenSslCurveName(localCurve);
-            auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(curveName));
-            ASSERT_NE(group, nullptr);
-            ASSERT_EQ(EC_KEY_set_group(ecKey.get(), group.get()), 1);
-            ASSERT_EQ(EC_KEY_generate_key(ecKey.get()), 1);
-            auto pkey = EVP_PKEY_Ptr(EVP_PKEY_new());
-            ASSERT_EQ(EVP_PKEY_set1_EC_KEY(pkey.get(), ecKey.get()), 1);
+            SCOPED_TRACE(testing::Message()
+                         << "local-curve-" << localCurve << "-keymint-curve-" << curve);
 
-            // Get encoded form of the public part of the locally generated key...
-            unsigned char* p = nullptr;
-            int encodedPublicKeySize = i2d_PUBKEY(pkey.get(), &p);
-            ASSERT_GT(encodedPublicKeySize, 0);
-            vector<uint8_t> encodedPublicKey(
-                    reinterpret_cast<const uint8_t*>(p),
-                    reinterpret_cast<const uint8_t*>(p + encodedPublicKeySize));
-            OPENSSL_free(p);
+            // Generate EC key locally (with access to private key material)
+            EVP_PKEY_Ptr localPrivKey;
+            vector<uint8_t> localPublicKey;
+            GenerateLocalEcKey(localCurve, &localPrivKey, &localPublicKey);
 
             // Generate EC key in KeyMint (only access to public key material)
-            vector<uint8_t> challenge = {0x41, 0x42};
-            EXPECT_EQ(
-                    ErrorCode::OK,
-                    GenerateKey(AuthorizationSetBuilder()
-                                        .Authorization(TAG_NO_AUTH_REQUIRED)
-                                        .Authorization(TAG_EC_CURVE, curve)
-                                        .Authorization(TAG_PURPOSE, KeyPurpose::AGREE_KEY)
-                                        .Authorization(TAG_ALGORITHM, Algorithm::EC)
-                                        .Authorization(TAG_ATTESTATION_APPLICATION_ID, {0x61, 0x62})
-                                        .Authorization(TAG_ATTESTATION_CHALLENGE, challenge)
-                                        .SetDefaultValidity()))
-                    << "Failed to generate key";
-            ASSERT_GT(cert_chain_.size(), 0);
-            X509_Ptr kmKeyCert(parse_cert_blob(cert_chain_[0].encodedCertificate));
-            ASSERT_NE(kmKeyCert, nullptr);
-            // Check that keyAgreement (bit 4) is set in KeyUsage
-            EXPECT_TRUE((X509_get_key_usage(kmKeyCert.get()) & X509v3_KU_KEY_AGREEMENT) != 0);
-            auto kmPkey = EVP_PKEY_Ptr(X509_get_pubkey(kmKeyCert.get()));
-            ASSERT_NE(kmPkey, nullptr);
-            if (dump_Attestations) {
-                for (size_t n = 0; n < cert_chain_.size(); n++) {
-                    std::cout << bin2hex(cert_chain_[n].encodedCertificate) << std::endl;
-                }
-            }
+            EVP_PKEY_Ptr kmPubKey;
+            GenerateKeyMintEcKey(curve, &kmPubKey);
 
             // Now that we have the two keys, we ask KeyMint to perform ECDH...
             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(encodedPublicKey.begin(), encodedPublicKey.end()),
+                          Finish(string(localPublicKey.begin(), localPublicKey.end()),
                                  &ZabFromKeyMintStr));
 
             } else {
                 // Otherwise if the keys are using the same curve, it should work.
-                EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::AGREE_KEY, AuthorizationSetBuilder()));
-                string ZabFromKeyMintStr;
-                EXPECT_EQ(ErrorCode::OK,
-                          Finish(string(encodedPublicKey.begin(), encodedPublicKey.end()),
-                                 &ZabFromKeyMintStr));
-                vector<uint8_t> ZabFromKeyMint(ZabFromKeyMintStr.begin(), ZabFromKeyMintStr.end());
-
-                // Perform local ECDH between the two keys so we can check if we get the same Zab..
-                auto ctx = EVP_PKEY_CTX_Ptr(EVP_PKEY_CTX_new(pkey.get(), nullptr));
-                ASSERT_NE(ctx, nullptr);
-                ASSERT_EQ(EVP_PKEY_derive_init(ctx.get()), 1);
-                ASSERT_EQ(EVP_PKEY_derive_set_peer(ctx.get(), kmPkey.get()), 1);
-                size_t ZabFromTestLen = 0;
-                ASSERT_EQ(EVP_PKEY_derive(ctx.get(), nullptr, &ZabFromTestLen), 1);
-                vector<uint8_t> ZabFromTest;
-                ZabFromTest.resize(ZabFromTestLen);
-                ASSERT_EQ(EVP_PKEY_derive(ctx.get(), ZabFromTest.data(), &ZabFromTestLen), 1);
-
-                EXPECT_EQ(ZabFromKeyMint, ZabFromTest);
+                CheckAgreement(std::move(kmPubKey), std::move(localPrivKey), localPublicKey);
             }
 
             CheckedDeleteKey();
@@ -6531,6 +7694,140 @@
     }
 }
 
+/*
+ * KeyAgreementTest.EcdhCurve25519
+ *
+ * Verifies that ECDH works for curve25519. This is also covered by the general
+ * KeyAgreementTest.Ecdh case, but is pulled out separately here because this curve was added after
+ * KeyMint 1.0.
+ */
+TEST_P(KeyAgreementTest, EcdhCurve25519) {
+    if (!Curve25519Supported()) {
+        GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+    }
+
+    // Generate EC key in KeyMint (only access to public key material)
+    EcCurve curve = EcCurve::CURVE_25519;
+    EVP_PKEY_Ptr kmPubKey = nullptr;
+    GenerateKeyMintEcKey(curve, &kmPubKey);
+
+    // Generate EC key on same curve locally (with access to private key material).
+    EVP_PKEY_Ptr privKey;
+    vector<uint8_t> encodedPublicKey;
+    GenerateLocalEcKey(curve, &privKey, &encodedPublicKey);
+
+    // Agree on a key between local and KeyMint and check it.
+    CheckAgreement(std::move(kmPubKey), std::move(privKey), encodedPublicKey);
+
+    CheckedDeleteKey();
+}
+
+/*
+ * KeyAgreementTest.EcdhCurve25519Imported
+ *
+ * Verifies that ECDH works for an imported curve25519 key.
+ */
+TEST_P(KeyAgreementTest, EcdhCurve25519Imported) {
+    if (!Curve25519Supported()) {
+        GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+    }
+
+    // Import x25519 key into KeyMint.
+    EcCurve curve = EcCurve::CURVE_25519;
+    ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+                                               .Authorization(TAG_NO_AUTH_REQUIRED)
+                                               .EcdsaKey(EcCurve::CURVE_25519)
+                                               .Authorization(TAG_PURPOSE, KeyPurpose::AGREE_KEY)
+                                               .SetDefaultValidity(),
+                                       KeyFormat::PKCS8, x25519_pkcs8_key));
+    ASSERT_GT(cert_chain_.size(), 0);
+    X509_Ptr kmKeyCert(parse_cert_blob(cert_chain_[0].encodedCertificate));
+    ASSERT_NE(kmKeyCert, nullptr);
+    EVP_PKEY_Ptr kmPubKey(X509_get_pubkey(kmKeyCert.get()));
+    ASSERT_NE(kmPubKey.get(), nullptr);
+
+    // Expect the import to emit corresponding public key data.
+    size_t kmPubKeySize = 32;
+    uint8_t kmPubKeyData[32];
+    ASSERT_EQ(1, EVP_PKEY_get_raw_public_key(kmPubKey.get(), kmPubKeyData, &kmPubKeySize));
+    ASSERT_EQ(kmPubKeySize, 32);
+    EXPECT_EQ(bin2hex(std::vector<uint8_t>(kmPubKeyData, kmPubKeyData + 32)),
+              bin2hex(std::vector<uint8_t>(x25519_pubkey.begin(), x25519_pubkey.end())));
+
+    // Generate EC key on same curve locally (with access to private key material).
+    EVP_PKEY_Ptr privKey;
+    vector<uint8_t> encodedPublicKey;
+    GenerateLocalEcKey(curve, &privKey, &encodedPublicKey);
+
+    // Agree on a key between local and KeyMint and check it.
+    CheckAgreement(std::move(kmPubKey), std::move(privKey), encodedPublicKey);
+
+    CheckedDeleteKey();
+}
+
+/*
+ * KeyAgreementTest.EcdhCurve25519InvalidSize
+ *
+ * Verifies that ECDH fails for curve25519 if the wrong size of public key is provided.
+ */
+TEST_P(KeyAgreementTest, EcdhCurve25519InvalidSize) {
+    if (!Curve25519Supported()) {
+        GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+    }
+
+    // Generate EC key in KeyMint (only access to public key material)
+    EcCurve curve = EcCurve::CURVE_25519;
+    EVP_PKEY_Ptr kmPubKey = nullptr;
+    GenerateKeyMintEcKey(curve, &kmPubKey);
+
+    // Generate EC key on same curve locally (with access to private key material).
+    EVP_PKEY_Ptr privKey;
+    vector<uint8_t> encodedPublicKey;
+    GenerateLocalEcKey(curve, &privKey, &encodedPublicKey);
+
+    ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::AGREE_KEY, AuthorizationSetBuilder()));
+    string ZabFromKeyMintStr;
+    // Send in an incomplete public key.
+    ASSERT_NE(ErrorCode::OK, Finish(string(encodedPublicKey.begin(), encodedPublicKey.end() - 1),
+                                    &ZabFromKeyMintStr));
+
+    CheckedDeleteKey();
+}
+
+/*
+ * KeyAgreementTest.EcdhCurve25519Mismatch
+ *
+ * Verifies that ECDH fails between curve25519 and other curves.
+ */
+TEST_P(KeyAgreementTest, EcdhCurve25519Mismatch) {
+    if (!Curve25519Supported()) {
+        GTEST_SKIP() << "Test not applicable to device that is not expected to support curve 25519";
+    }
+
+    // Generate EC key in KeyMint (only access to public key material)
+    EcCurve curve = EcCurve::CURVE_25519;
+    EVP_PKEY_Ptr kmPubKey = nullptr;
+    GenerateKeyMintEcKey(curve, &kmPubKey);
+
+    for (auto localCurve : ValidCurves()) {
+        if (localCurve == curve) {
+            continue;
+        }
+        // Generate EC key on a different curve locally (with access to private key material).
+        EVP_PKEY_Ptr privKey;
+        vector<uint8_t> encodedPublicKey;
+        GenerateLocalEcKey(localCurve, &privKey, &encodedPublicKey);
+
+        ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::AGREE_KEY, AuthorizationSetBuilder()));
+        string ZabFromKeyMintStr;
+        EXPECT_EQ(ErrorCode::INVALID_ARGUMENT,
+                  Finish(string(encodedPublicKey.begin(), encodedPublicKey.end()),
+                         &ZabFromKeyMintStr));
+    }
+
+    CheckedDeleteKey();
+}
+
 INSTANTIATE_KEYMINT_AIDL_TEST(KeyAgreementTest);
 
 using DestroyAttestationIdsTest = KeyMintAidlTestBase;
@@ -6580,14 +7877,23 @@
             });
 
     for (const auto& keyData : {aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData}) {
+        // Strongbox may not support factory attestation. Key creation might fail with
+        // ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED
+        if (SecLevel() == SecurityLevel::STRONGBOX && keyData.blob.size() == 0U) {
+            continue;
+        }
         ASSERT_GT(keyData.blob.size(), 0U);
         AuthorizationSet crypto_params = SecLevelAuthorizations(keyData.characteristics);
         EXPECT_TRUE(crypto_params.Contains(TAG_EARLY_BOOT_ONLY)) << crypto_params;
     }
     CheckedDeleteKey(&aesKeyData.blob);
     CheckedDeleteKey(&hmacKeyData.blob);
-    CheckedDeleteKey(&rsaKeyData.blob);
-    CheckedDeleteKey(&ecdsaKeyData.blob);
+    if (rsaKeyData.blob.size() != 0U) {
+        CheckedDeleteKey(&rsaKeyData.blob);
+    }
+    if (ecdsaKeyData.blob.size() != 0U) {
+        CheckedDeleteKey(&ecdsaKeyData.blob);
+    }
 }
 
 /*
@@ -6708,6 +8014,18 @@
 
 INSTANTIATE_KEYMINT_AIDL_TEST(UnlockedDeviceRequiredTest);
 
+using VsrRequirementTest = KeyMintAidlTestBase;
+
+TEST_P(VsrRequirementTest, Vsr13Test) {
+    int vsr_api_level = get_vsr_api_level();
+    if (vsr_api_level < 33) {
+        GTEST_SKIP() << "Applies only to VSR API level 33, this device is: " << vsr_api_level;
+    }
+    EXPECT_GE(AidlVersion(), 2) << "VSR 13+ requires KeyMint version 2";
+}
+
+INSTANTIATE_KEYMINT_AIDL_TEST(VsrRequirementTest);
+
 }  // namespace aidl::android::hardware::security::keymint::test
 
 int main(int argc, char** argv) {
@@ -6732,9 +8050,11 @@
             } else {
                 std::cout << "NOT dumping attestations" << std::endl;
             }
-            // TODO(drysdale): Remove this flag when available KeyMint devices comply with spec
-            if (std::string(argv[i]) == "--check_patchLevels") {
-                aidl::android::hardware::security::keymint::test::check_patchLevels = true;
+            if (std::string(argv[i]) == "--skip_boot_pl_check") {
+                // Allow checks of BOOT_PATCHLEVEL to be disabled, so that the tests can
+                // be run in emulated environments that don't have the normal bootloader
+                // interactions.
+                aidl::android::hardware::security::keymint::test::check_boot_pl = false;
             }
         }
     }
diff --git a/security/keymint/aidl/vts/functional/SecureElementProvisioningTest.cpp b/security/keymint/aidl/vts/functional/SecureElementProvisioningTest.cpp
new file mode 100644
index 0000000..c9a156d
--- /dev/null
+++ b/security/keymint/aidl/vts/functional/SecureElementProvisioningTest.cpp
@@ -0,0 +1,383 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "keymint_2_se_provisioning_test"
+
+#include <map>
+#include <memory>
+#include <vector>
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+
+#include <cppbor_parse.h>
+#include <keymaster/cppcose/cppcose.h>
+#include <keymint_support/key_param_output.h>
+
+#include "KeyMintAidlTestBase.h"
+
+namespace aidl::android::hardware::security::keymint::test {
+
+using std::array;
+using std::map;
+using std::shared_ptr;
+using std::vector;
+
+constexpr int kRoTVersion1 = 40001;
+
+class SecureElementProvisioningTest : public testing::Test {
+  protected:
+    static void SetUpTestSuite() {
+        auto params = ::android::getAidlHalInstanceNames(IKeyMintDevice::descriptor);
+        for (auto& param : params) {
+            ASSERT_TRUE(AServiceManager_isDeclared(param.c_str()))
+                    << "IKeyMintDevice instance " << param << " found but not declared.";
+            ::ndk::SpAIBinder binder(AServiceManager_waitForService(param.c_str()));
+            auto keymint = IKeyMintDevice::fromBinder(binder);
+            ASSERT_NE(keymint, nullptr) << "Failed to get IKeyMintDevice instance " << param;
+
+            KeyMintHardwareInfo info;
+            ASSERT_TRUE(keymint->getHardwareInfo(&info).isOk());
+            ASSERT_EQ(keymints_.count(info.securityLevel), 0)
+                    << "There must be exactly one IKeyMintDevice with security level "
+                    << info.securityLevel;
+
+            keymints_[info.securityLevel] = std::move(keymint);
+        }
+    }
+
+    void validateMacedRootOfTrust(const vector<uint8_t>& rootOfTrust) {
+        SCOPED_TRACE(testing::Message() << "RoT: " << bin2hex(rootOfTrust));
+
+        const auto [macItem, macEndPos, macErrMsg] = cppbor::parse(rootOfTrust);
+        ASSERT_TRUE(macItem) << "Root of trust parsing failed: " << macErrMsg;
+        ASSERT_EQ(macItem->semanticTagCount(), 1);
+        ASSERT_EQ(macItem->semanticTag(0), cppcose::kCoseMac0SemanticTag);
+        ASSERT_TRUE(macItem->asArray());
+        ASSERT_EQ(macItem->asArray()->size(), cppcose::kCoseMac0EntryCount);
+
+        const auto& protectedItem = macItem->asArray()->get(cppcose::kCoseMac0ProtectedParams);
+        ASSERT_TRUE(protectedItem);
+        ASSERT_TRUE(protectedItem->asBstr());
+        const auto [protMap, protEndPos, protErrMsg] = cppbor::parse(protectedItem->asBstr());
+        ASSERT_TRUE(protMap);
+        ASSERT_TRUE(protMap->asMap());
+        ASSERT_EQ(protMap->asMap()->size(), 1);
+
+        const auto& algorithm = protMap->asMap()->get(cppcose::ALGORITHM);
+        ASSERT_TRUE(algorithm);
+        ASSERT_TRUE(algorithm->asInt());
+        ASSERT_EQ(algorithm->asInt()->value(), cppcose::HMAC_256);
+
+        const auto& unprotItem = macItem->asArray()->get(cppcose::kCoseMac0UnprotectedParams);
+        ASSERT_TRUE(unprotItem);
+        ASSERT_TRUE(unprotItem->asMap());
+        ASSERT_EQ(unprotItem->asMap()->size(), 0);
+
+        const auto& payload = macItem->asArray()->get(cppcose::kCoseMac0Payload);
+        ASSERT_TRUE(payload);
+        ASSERT_TRUE(payload->asBstr());
+        validateRootOfTrust(payload->asBstr()->value());
+
+        const auto& tag = macItem->asArray()->get(cppcose::kCoseMac0Tag);
+        ASSERT_TRUE(tag);
+        ASSERT_TRUE(tag->asBstr());
+        ASSERT_EQ(tag->asBstr()->value().size(), 32);
+        // Cannot validate tag correctness.  Only the secure side has the necessary key.
+    }
+
+    void validateRootOfTrust(const vector<uint8_t>& payload) {
+        SCOPED_TRACE(testing::Message() << "RoT payload: " << bin2hex(payload));
+
+        const auto [rot, rotPos, rotErrMsg] = cppbor::parse(payload);
+        ASSERT_TRUE(rot);
+        ASSERT_EQ(rot->semanticTagCount(), 1);
+        ASSERT_EQ(rot->semanticTag(), kRoTVersion1);
+        ASSERT_TRUE(rot->asArray());
+        ASSERT_EQ(rot->asArray()->size(), 5);
+
+        size_t pos = 0;
+
+        const auto& vbKey = rot->asArray()->get(pos++);
+        ASSERT_TRUE(vbKey);
+        ASSERT_TRUE(vbKey->asBstr());
+
+        const auto& deviceLocked = rot->asArray()->get(pos++);
+        ASSERT_TRUE(deviceLocked);
+        ASSERT_TRUE(deviceLocked->asBool());
+
+        const auto& verifiedBootState = rot->asArray()->get(pos++);
+        ASSERT_TRUE(verifiedBootState);
+        ASSERT_TRUE(verifiedBootState->asInt());
+
+        const auto& verifiedBootHash = rot->asArray()->get(pos++);
+        ASSERT_TRUE(verifiedBootHash);
+        ASSERT_TRUE(verifiedBootHash->asBstr());
+
+        const auto& bootPatchLevel = rot->asArray()->get(pos++);
+        ASSERT_TRUE(bootPatchLevel);
+        ASSERT_TRUE(bootPatchLevel->asInt());
+
+        verify_root_of_trust(vbKey->asBstr()->value(), deviceLocked->asBool()->value(),
+                             static_cast<VerifiedBoot>(verifiedBootState->asInt()->value()),
+                             verifiedBootHash->asBstr()->value());
+    }
+
+    int32_t AidlVersion(shared_ptr<IKeyMintDevice> keymint) {
+        int32_t version = 0;
+        auto status = keymint->getInterfaceVersion(&version);
+        if (!status.isOk()) {
+            ADD_FAILURE() << "Failed to determine interface version";
+        }
+        return version;
+    }
+
+    static map<SecurityLevel, shared_ptr<IKeyMintDevice>> keymints_;
+};
+
+map<SecurityLevel, shared_ptr<IKeyMintDevice>> SecureElementProvisioningTest::keymints_;
+
+TEST_F(SecureElementProvisioningTest, ValidConfigurations) {
+    if (keymints_.empty()) {
+        GTEST_SKIP() << "Test not applicable to device with no KeyMint devices";
+    }
+    // TEE is required
+    ASSERT_EQ(keymints_.count(SecurityLevel::TRUSTED_ENVIRONMENT), 1);
+    // StrongBox is optional
+    ASSERT_LE(keymints_.count(SecurityLevel::STRONGBOX), 1);
+}
+
+TEST_F(SecureElementProvisioningTest, TeeOnly) {
+    if (keymints_.count(SecurityLevel::TRUSTED_ENVIRONMENT) == 0) {
+        GTEST_SKIP() << "Test not applicable to device with no TEE KeyMint device";
+    }
+    auto tee = keymints_.find(SecurityLevel::TRUSTED_ENVIRONMENT)->second;
+    // Execute the test only for KeyMint version >= 2.
+    if (AidlVersion(tee) < 2) {
+        GTEST_SKIP() << "Test not applicable to TEE KeyMint device before v2";
+    }
+
+    array<uint8_t, 16> challenge1 = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+    array<uint8_t, 16> challenge2 = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+    vector<uint8_t> rootOfTrust1;
+    Status result = tee->getRootOfTrust(challenge1, &rootOfTrust1);
+    ASSERT_TRUE(result.isOk()) << "getRootOfTrust returned " << result.getServiceSpecificError();
+    validateMacedRootOfTrust(rootOfTrust1);
+
+    vector<uint8_t> rootOfTrust2;
+    result = tee->getRootOfTrust(challenge2, &rootOfTrust2);
+    ASSERT_TRUE(result.isOk());
+    validateMacedRootOfTrust(rootOfTrust2);
+    ASSERT_NE(rootOfTrust1, rootOfTrust2);
+
+    vector<uint8_t> rootOfTrust3;
+    result = tee->getRootOfTrust(challenge1, &rootOfTrust3);
+    ASSERT_TRUE(result.isOk());
+    ASSERT_EQ(rootOfTrust1, rootOfTrust3);
+}
+
+TEST_F(SecureElementProvisioningTest, TeeDoesNotImplementStrongBoxMethods) {
+    if (keymints_.count(SecurityLevel::TRUSTED_ENVIRONMENT) == 0) {
+        GTEST_SKIP() << "Test not applicable to device with no TEE KeyMint device";
+    }
+    auto tee = keymints_.find(SecurityLevel::TRUSTED_ENVIRONMENT)->second;
+    // Execute the test only for KeyMint version >= 2.
+    if (AidlVersion(tee) < 2) {
+        GTEST_SKIP() << "Test not applicable to TEE KeyMint device before v2";
+    }
+
+    array<uint8_t, 16> challenge;
+    Status result = tee->getRootOfTrustChallenge(&challenge);
+    ASSERT_FALSE(result.isOk());
+    ASSERT_EQ(result.getExceptionCode(), EX_SERVICE_SPECIFIC);
+    ASSERT_EQ(static_cast<ErrorCode>(result.getServiceSpecificError()), ErrorCode::UNIMPLEMENTED);
+
+    result = tee->sendRootOfTrust({});
+    ASSERT_FALSE(result.isOk());
+    ASSERT_EQ(result.getExceptionCode(), EX_SERVICE_SPECIFIC);
+    ASSERT_EQ(static_cast<ErrorCode>(result.getServiceSpecificError()), ErrorCode::UNIMPLEMENTED);
+}
+
+TEST_F(SecureElementProvisioningTest, StrongBoxDoesNotImplementTeeMethods) {
+    if (keymints_.count(SecurityLevel::STRONGBOX) == 0) {
+        // Need a StrongBox to provision.
+        GTEST_SKIP() << "Test not applicable to device with no StrongBox KeyMint device";
+    }
+    // Execute the test only for KeyMint version >= 2.
+    auto sb = keymints_.find(SecurityLevel::STRONGBOX)->second;
+    if (AidlVersion(sb) < 2) {
+        GTEST_SKIP() << "Test not applicable to StrongBox KeyMint device before v2";
+    }
+
+    vector<uint8_t> rootOfTrust;
+    Status result = sb->getRootOfTrust({}, &rootOfTrust);
+    ASSERT_FALSE(result.isOk());
+    ASSERT_EQ(result.getExceptionCode(), EX_SERVICE_SPECIFIC);
+    ASSERT_EQ(static_cast<ErrorCode>(result.getServiceSpecificError()), ErrorCode::UNIMPLEMENTED);
+}
+
+TEST_F(SecureElementProvisioningTest, UnimplementedTest) {
+    if (keymints_.count(SecurityLevel::STRONGBOX) == 0) {
+        // Need a StrongBox to provision.
+        GTEST_SKIP() << "Test not applicable to device with no StrongBox KeyMint device";
+    }
+    // Execute the test only for KeyMint version >= 2.
+    auto sb = keymints_.find(SecurityLevel::STRONGBOX)->second;
+    if (AidlVersion(sb) < 2) {
+        GTEST_SKIP() << "Test not applicable to StrongBox KeyMint device before v2";
+    }
+
+    if (keymints_.count(SecurityLevel::TRUSTED_ENVIRONMENT) == 0) {
+        GTEST_SKIP() << "Test not applicable to device with no TEE KeyMint device";
+    }
+    auto tee = keymints_.find(SecurityLevel::TRUSTED_ENVIRONMENT)->second;
+    if (AidlVersion(tee) < 2) {
+        GTEST_SKIP() << "Test not applicable to TEE KeyMint device before v2";
+    }
+
+    array<uint8_t, 16> challenge;
+    Status result = sb->getRootOfTrustChallenge(&challenge);
+    if (!result.isOk()) {
+        // Strongbox does not have to implement this feature if it has uses an alternative mechanism
+        // to provision the root of trust.  In that case it MUST return UNIMPLEMENTED, both from
+        // getRootOfTrustChallenge() and from sendRootOfTrust().
+        ASSERT_EQ(result.getExceptionCode(), EX_SERVICE_SPECIFIC);
+        ASSERT_EQ(static_cast<ErrorCode>(result.getServiceSpecificError()),
+                  ErrorCode::UNIMPLEMENTED);
+
+        result = sb->sendRootOfTrust({});
+        ASSERT_EQ(result.getExceptionCode(), EX_SERVICE_SPECIFIC);
+        ASSERT_EQ(static_cast<ErrorCode>(result.getServiceSpecificError()),
+                  ErrorCode::UNIMPLEMENTED);
+
+        SUCCEED() << "This Strongbox implementation does not use late root of trust delivery.";
+        return;
+    }
+}
+
+TEST_F(SecureElementProvisioningTest, ChallengeQualityTest) {
+    if (keymints_.count(SecurityLevel::STRONGBOX) == 0) {
+        // Need a StrongBox to provision.
+        GTEST_SKIP() << "Test not applicable to device with no StrongBox KeyMint device";
+    }
+    // Execute the test only for KeyMint version >= 2.
+    auto sb = keymints_.find(SecurityLevel::STRONGBOX)->second;
+    if (AidlVersion(sb) < 2) {
+        GTEST_SKIP() << "Test not applicable to StrongBox KeyMint device before v2";
+    }
+
+    array<uint8_t, 16> challenge1;
+    Status result = sb->getRootOfTrustChallenge(&challenge1);
+    if (!result.isOk()) return;
+
+    array<uint8_t, 16> challenge2;
+    result = sb->getRootOfTrustChallenge(&challenge2);
+    ASSERT_TRUE(result.isOk());
+    ASSERT_NE(challenge1, challenge2);
+
+    // TODO: When we add entropy testing in other relevant places in these tests, add it here, too,
+    // to verify that challenges appear to have adequate entropy.
+}
+
+TEST_F(SecureElementProvisioningTest, ProvisioningTest) {
+    if (keymints_.count(SecurityLevel::STRONGBOX) == 0) {
+        // Need a StrongBox to provision.
+        GTEST_SKIP() << "Test not applicable to device with no StrongBox KeyMint device";
+    }
+    // Execute the test only for KeyMint version >= 2.
+    auto sb = keymints_.find(SecurityLevel::STRONGBOX)->second;
+    if (AidlVersion(sb) < 2) {
+        GTEST_SKIP() << "Test not applicable to StrongBox KeyMint device before v2";
+    }
+
+    if (keymints_.count(SecurityLevel::TRUSTED_ENVIRONMENT) == 0) {
+        GTEST_SKIP() << "Test not applicable to device with no TEE KeyMint device";
+    }
+    // Execute the test only for KeyMint version >= 2.
+    auto tee = keymints_.find(SecurityLevel::TRUSTED_ENVIRONMENT)->second;
+    if (AidlVersion(tee) < 2) {
+        GTEST_SKIP() << "Test not applicable to TEE KeyMint device before v2";
+    }
+
+    array<uint8_t, 16> challenge;
+    Status result = sb->getRootOfTrustChallenge(&challenge);
+    if (!result.isOk()) return;
+
+    vector<uint8_t> rootOfTrust;
+    result = tee->getRootOfTrust(challenge, &rootOfTrust);
+    ASSERT_TRUE(result.isOk());
+
+    validateMacedRootOfTrust(rootOfTrust);
+
+    result = sb->sendRootOfTrust(rootOfTrust);
+    ASSERT_TRUE(result.isOk());
+
+    // Sending again must fail, because a new challenge is required.
+    result = sb->sendRootOfTrust(rootOfTrust);
+    ASSERT_FALSE(result.isOk());
+}
+
+TEST_F(SecureElementProvisioningTest, InvalidProvisioningTest) {
+    if (keymints_.count(SecurityLevel::STRONGBOX) == 0) {
+        // Need a StrongBox to provision.
+        GTEST_SKIP() << "Test not applicable to device with no StrongBox KeyMint device";
+    }
+    // Execute the test only for KeyMint version >= 2.
+    auto sb = keymints_.find(SecurityLevel::STRONGBOX)->second;
+    if (AidlVersion(sb) < 2) {
+        GTEST_SKIP() << "Test not applicable to StrongBox KeyMint device before v2";
+    }
+
+    if (keymints_.count(SecurityLevel::TRUSTED_ENVIRONMENT) == 0) {
+        GTEST_SKIP() << "Test not applicable to device with no TEE KeyMint device";
+    }
+    // Execute the test only for KeyMint version >= 2.
+    auto tee = keymints_.find(SecurityLevel::TRUSTED_ENVIRONMENT)->second;
+    if (AidlVersion(tee) < 2) {
+        GTEST_SKIP() << "Test not applicable to TEE KeyMint device before v2";
+    }
+
+    array<uint8_t, 16> challenge;
+    Status result = sb->getRootOfTrustChallenge(&challenge);
+    if (!result.isOk()) return;
+
+    result = sb->sendRootOfTrust({});
+    ASSERT_FALSE(result.isOk());
+    ASSERT_EQ(result.getExceptionCode(), EX_SERVICE_SPECIFIC);
+    ASSERT_EQ(static_cast<ErrorCode>(result.getServiceSpecificError()),
+              ErrorCode::VERIFICATION_FAILED);
+
+    vector<uint8_t> rootOfTrust;
+    result = tee->getRootOfTrust(challenge, &rootOfTrust);
+    ASSERT_TRUE(result.isOk());
+
+    validateMacedRootOfTrust(rootOfTrust);
+
+    vector<uint8_t> corruptedRootOfTrust = rootOfTrust;
+    corruptedRootOfTrust[corruptedRootOfTrust.size() / 2]++;
+    result = sb->sendRootOfTrust(corruptedRootOfTrust);
+    ASSERT_FALSE(result.isOk());
+    ASSERT_EQ(result.getExceptionCode(), EX_SERVICE_SPECIFIC);
+    ASSERT_EQ(static_cast<ErrorCode>(result.getServiceSpecificError()),
+              ErrorCode::VERIFICATION_FAILED);
+
+    // Now try the correct RoT
+    result = sb->sendRootOfTrust(rootOfTrust);
+    ASSERT_TRUE(result.isOk());
+}
+
+}  // namespace aidl::android::hardware::security::keymint::test
diff --git a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
index 76fb79b..7184613 100644
--- a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
+++ b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
@@ -20,6 +20,7 @@
 #include <aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.h>
 #include <aidl/android/hardware/security/keymint/SecurityLevel.h>
 #include <android/binder_manager.h>
+#include <binder/IServiceManager.h>
 #include <cppbor_parse.h>
 #include <gmock/gmock.h>
 #include <keymaster/cppcose/cppcose.h>
@@ -29,6 +30,7 @@
 #include <openssl/ec_key.h>
 #include <openssl/x509.h>
 #include <remote_prov/remote_prov_utils.h>
+#include <set>
 #include <vector>
 
 #include "KeyMintAidlTestBase.h"
@@ -40,6 +42,8 @@
 
 namespace {
 
+constexpr int32_t VERSION_WITH_UNIQUE_ID_SUPPORT = 2;
+
 #define INSTANTIATE_REM_PROV_AIDL_TEST(name)                                         \
     GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(name);                             \
     INSTANTIATE_TEST_SUITE_P(                                                        \
@@ -47,11 +51,28 @@
             testing::ValuesIn(VtsRemotelyProvisionedComponentTests::build_params()), \
             ::android::PrintInstanceNameToString)
 
+using ::android::sp;
 using bytevec = std::vector<uint8_t>;
 using testing::MatchesRegex;
 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));
@@ -164,6 +185,7 @@
             provisionable_ = IRemotelyProvisionedComponent::fromBinder(binder);
         }
         ASSERT_NE(provisionable_, nullptr);
+        ASSERT_TRUE(provisionable_->getHardwareInfo(&rpcHardwareInfo).isOk());
     }
 
     static vector<string> build_params() {
@@ -173,8 +195,70 @@
 
   protected:
     std::shared_ptr<IRemotelyProvisionedComponent> provisionable_;
+    RpcHardwareInfo rpcHardwareInfo;
 };
 
+/**
+ * Verify that every implementation reports a different unique id.
+ */
+TEST(NonParameterizedTests, eachRpcHasAUniqueId) {
+    std::set<std::string> uniqueIds;
+    for (auto hal : ::android::getAidlHalInstanceNames(IRemotelyProvisionedComponent::descriptor)) {
+        ASSERT_TRUE(AServiceManager_isDeclared(hal.c_str()));
+        ::ndk::SpAIBinder binder(AServiceManager_waitForService(hal.c_str()));
+        std::shared_ptr<IRemotelyProvisionedComponent> rpc =
+                IRemotelyProvisionedComponent::fromBinder(binder);
+        ASSERT_NE(rpc, nullptr);
+
+        RpcHardwareInfo hwInfo;
+        ASSERT_TRUE(rpc->getHardwareInfo(&hwInfo).isOk());
+
+        int32_t version;
+        ASSERT_TRUE(rpc->getInterfaceVersion(&version).isOk());
+        if (version >= VERSION_WITH_UNIQUE_ID_SUPPORT) {
+            ASSERT_TRUE(hwInfo.uniqueId);
+            auto [_, wasInserted] = uniqueIds.insert(*hwInfo.uniqueId);
+            EXPECT_TRUE(wasInserted);
+        } else {
+            ASSERT_FALSE(hwInfo.uniqueId);
+        }
+    }
+}
+
+using GetHardwareInfoTests = VtsRemotelyProvisionedComponentTests;
+
+INSTANTIATE_REM_PROV_AIDL_TEST(GetHardwareInfoTests);
+
+/**
+ * Verify that a valid curve is reported by the implementation.
+ */
+TEST_P(GetHardwareInfoTests, supportsValidCurve) {
+    RpcHardwareInfo hwInfo;
+    ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
+
+    const std::set<int> validCurves = {RpcHardwareInfo::CURVE_P256, RpcHardwareInfo::CURVE_25519};
+    ASSERT_EQ(validCurves.count(hwInfo.supportedEekCurve), 1)
+            << "Invalid curve: " << hwInfo.supportedEekCurve;
+}
+
+/**
+ * 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) {
+        return;
+    }
+
+    RpcHardwareInfo hwInfo;
+    ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
+    ASSERT_TRUE(hwInfo.uniqueId);
+    EXPECT_GE(hwInfo.uniqueId->size(), 1);
+    EXPECT_LE(hwInfo.uniqueId->size(), 32);
+}
+
 using GenerateKeyTests = VtsRemotelyProvisionedComponentTests;
 
 INSTANTIATE_REM_PROV_AIDL_TEST(GenerateKeyTests);
@@ -236,9 +320,11 @@
     vector<Certificate> attested_key_cert_chain = std::move(creationResult.certificateChain);
     EXPECT_EQ(attested_key_cert_chain.size(), 1);
 
+    int32_t aidl_version = 0;
+    ASSERT_TRUE(keyMint->getInterfaceVersion(&aidl_version).isOk());
     AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
     AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
-    EXPECT_TRUE(verify_attestation_record("foo", "bar", sw_enforced, hw_enforced,
+    EXPECT_TRUE(verify_attestation_record(aidl_version, "foo", "bar", sw_enforced, hw_enforced,
                                           info.securityLevel,
                                           attested_key_cert_chain[0].encodedCertificate));
 
@@ -272,13 +358,11 @@
 
 class CertificateRequestTest : public VtsRemotelyProvisionedComponentTests {
   protected:
-    CertificateRequestTest() : eekId_(string_to_bytevec("eekid")), challenge_(randomBytes(32)) {
-        generateTestEekChain(3);
-    }
+    CertificateRequestTest() : eekId_(string_to_bytevec("eekid")), challenge_(randomBytes(64)) {}
 
     void generateTestEekChain(size_t eekLength) {
-        auto chain = generateEekChain(eekLength, eekId_);
-        EXPECT_TRUE(chain) << chain.message();
+        auto chain = generateEekChain(rpcHardwareInfo.supportedEekCurve, eekLength, eekId_);
+        ASSERT_TRUE(chain) << chain.message();
         if (chain) testEekChain_ = chain.moveValue();
         testEekLength_ = eekLength;
     }
@@ -298,6 +382,17 @@
         }
     }
 
+    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) {
@@ -310,9 +405,7 @@
         ASSERT_TRUE(senderPubkey) << senderPubkey.message();
         EXPECT_EQ(senderPubkey->second, eekId_);
 
-        auto sessionKey =
-                x25519_HKDF_DeriveKey(testEekChain_.last_pubkey, testEekChain_.last_privkey,
-                                      senderPubkey->first, false /* senderIsA */);
+        auto sessionKey = getSessionKey(senderPubkey);
         ASSERT_TRUE(sessionKey) << sessionKey.message();
 
         auto protectedDataPayload =
@@ -322,7 +415,8 @@
         auto [parsedPayload, __, payloadErrMsg] = cppbor::parse(*protectedDataPayload);
         ASSERT_TRUE(parsedPayload) << "Failed to parse payload: " << payloadErrMsg;
         ASSERT_TRUE(parsedPayload->asArray());
-        EXPECT_EQ(parsedPayload->asArray()->size(), 2U);
+        // Strongbox may contain additional certificate chain.
+        EXPECT_LE(parsedPayload->asArray()->size(), 3U);
 
         auto& signedMac = parsedPayload->asArray()->get(0);
         auto& bcc = parsedPayload->asArray()->get(1);
@@ -337,8 +431,9 @@
         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_)
@@ -364,6 +459,80 @@
         }
     }
 
+    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_;
@@ -406,6 +575,7 @@
     bytevec keysToSignMac;
     DeviceInfo deviceInfo;
     ProtectedData protectedData;
+    generateTestEekChain(3);
     auto status = provisionable_->generateCertificateRequest(
             testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
             &protectedData, &keysToSignMac);
@@ -445,8 +615,8 @@
     DeviceInfo deviceInfo;
     ProtectedData protectedData;
     auto status = provisionable_->generateCertificateRequest(
-            testMode, {} /* keysToSign */, getProdEekChain(), challenge_, &deviceInfo,
-            &protectedData, &keysToSignMac);
+            testMode, {} /* keysToSign */, getProdEekChain(rpcHardwareInfo.supportedEekCurve),
+            challenge_, &deviceInfo, &protectedData, &keysToSignMac);
     EXPECT_TRUE(status.isOk());
 }
 
@@ -486,8 +656,8 @@
     DeviceInfo deviceInfo;
     ProtectedData protectedData;
     auto status = provisionable_->generateCertificateRequest(
-            testMode, keysToSign_, getProdEekChain(), challenge_, &deviceInfo, &protectedData,
-            &keysToSignMac);
+            testMode, keysToSign_, getProdEekChain(rpcHardwareInfo.supportedEekCurve), challenge_,
+            &deviceInfo, &protectedData, &keysToSignMac);
     EXPECT_TRUE(status.isOk());
 }
 
@@ -497,11 +667,14 @@
 TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_testMode) {
     bool testMode = true;
     generateKeys(testMode, 1 /* numKeys */);
-    MacedPublicKey keyWithCorruptMac = corrupt_maced_key(keysToSign_[0]).moveValue();
+    auto result = corrupt_maced_key(keysToSign_[0]);
+    ASSERT_TRUE(result) << result.moveMessage();
+    MacedPublicKey keyWithCorruptMac = result.moveValue();
 
     bytevec keysToSignMac;
     DeviceInfo deviceInfo;
     ProtectedData protectedData;
+    generateTestEekChain(3);
     auto status = provisionable_->generateCertificateRequest(
             testMode, {keyWithCorruptMac}, testEekChain_.chain, challenge_, &deviceInfo,
             &protectedData, &keysToSignMac);
@@ -515,14 +688,16 @@
 TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_prodMode) {
     bool testMode = false;
     generateKeys(testMode, 1 /* numKeys */);
-    MacedPublicKey keyWithCorruptMac = corrupt_maced_key(keysToSign_[0]).moveValue();
+    auto result = corrupt_maced_key(keysToSign_[0]);
+    ASSERT_TRUE(result) << result.moveMessage();
+    MacedPublicKey keyWithCorruptMac = result.moveValue();
 
     bytevec keysToSignMac;
     DeviceInfo deviceInfo;
     ProtectedData protectedData;
     auto status = provisionable_->generateCertificateRequest(
-            testMode, {keyWithCorruptMac}, getProdEekChain(), challenge_, &deviceInfo,
-            &protectedData, &keysToSignMac);
+            testMode, {keyWithCorruptMac}, getProdEekChain(rpcHardwareInfo.supportedEekCurve),
+            challenge_, &deviceInfo, &protectedData, &keysToSignMac);
     ASSERT_FALSE(status.isOk()) << status.getMessage();
     EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
 }
@@ -535,7 +710,7 @@
     bool testMode = false;
     generateKeys(testMode, 4 /* numKeys */);
 
-    auto prodEekChain = getProdEekChain();
+    auto prodEekChain = getProdEekChain(rpcHardwareInfo.supportedEekCurve);
     auto [parsedChain, _, parseErr] = cppbor::parse(prodEekChain);
     ASSERT_NE(parsedChain, nullptr) << parseErr;
     ASSERT_NE(parsedChain->asArray(), nullptr);
@@ -566,7 +741,7 @@
 
     // Build an EEK chain that omits the first self-signed cert.
     auto truncatedChain = cppbor::Array();
-    auto [chain, _, parseErr] = cppbor::parse(getProdEekChain());
+    auto [chain, _, parseErr] = cppbor::parse(getProdEekChain(rpcHardwareInfo.supportedEekCurve));
     ASSERT_TRUE(chain);
     auto eekChain = chain->asArray();
     ASSERT_NE(eekChain, nullptr);
@@ -594,6 +769,7 @@
     bytevec keysToSignMac;
     DeviceInfo deviceInfo;
     ProtectedData protectedData;
+    generateTestEekChain(3);
     auto status = provisionable_->generateCertificateRequest(
             true /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
             &protectedData, &keysToSignMac);
@@ -612,6 +788,7 @@
     bytevec keysToSignMac;
     DeviceInfo deviceInfo;
     ProtectedData protectedData;
+    generateTestEekChain(3);
     auto status = provisionable_->generateCertificateRequest(
             false /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
             &protectedData, &keysToSignMac);
diff --git a/security/keymint/aidl/vts/performance/Android.bp b/security/keymint/aidl/vts/performance/Android.bp
index 79ed0d5..7e3a3e5 100644
--- a/security/keymint/aidl/vts/performance/Android.bp
+++ b/security/keymint/aidl/vts/performance/Android.bp
@@ -27,6 +27,7 @@
     name: "VtsAidlKeyMintBenchmarkTest",
     defaults: [
         "VtsHalTargetTestDefaults",
+        "keymint_use_latest_hal_aidl_ndk_static",
         "use_libaidlvintf_gtest_helper_static",
     ],
     srcs: [
@@ -39,8 +40,7 @@
         "libkeymint_support",
     ],
     static_libs: [
-        "android.hardware.security.keymint-V1-ndk_platform",
-        "android.hardware.security.secureclock-V1-ndk_platform",
+        "android.hardware.security.secureclock-V1-ndk",
         "libcppbor_external",
         "libchrome",
     ],
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 9e218b6..bf2ab02 100644
--- a/security/keymint/support/Android.bp
+++ b/security/keymint/support/Android.bp
@@ -25,6 +25,7 @@
 
 cc_library {
     name: "libkeymint_support",
+    vendor_available: true,
     cflags: [
         "-Wall",
         "-Wextra",
@@ -39,11 +40,14 @@
     export_include_dirs: [
         "include",
     ],
+    defaults: [
+        "keymint_use_latest_hal_aidl_ndk_shared",
+    ],
     shared_libs: [
-        "android.hardware.security.keymint-V1-ndk_platform",
         "libbase",
         "libcrypto",
         "libutils",
+        "libhardware",
     ],
 }
 
@@ -56,11 +60,15 @@
     export_include_dirs: [
         "include",
     ],
+    defaults: [
+        "keymint_use_latest_hal_aidl_ndk_shared",
+    ],
     shared_libs: [
         "libbase",
         "libcppbor_external",
         "libcppcose_rkp",
         "libcrypto",
+        "libkeymaster_portable",
         "libjsoncpp",
     ],
 }
@@ -72,6 +80,9 @@
         "libgmock",
         "libgtest_main",
     ],
+    defaults: [
+        "keymint_use_latest_hal_aidl_ndk_shared",
+    ],
     shared_libs: [
         "libbase",
         "libcppbor_external",
diff --git a/security/keymint/support/OWNERS b/security/keymint/support/OWNERS
deleted file mode 100644
index a93b171..0000000
--- a/security/keymint/support/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-jbires@google.com
-jdanis@google.com
-seleneh@google.com
-swillden@google.com
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 406b7a9..f3b8608 100644
--- a/security/keymint/support/include/remote_prov/remote_prov_utils.h
+++ b/security/keymint/support/include/remote_prov/remote_prov_utils.h
@@ -52,6 +52,34 @@
         0x31, 0xbf, 0x6b, 0xe8, 0x1e, 0x35, 0xe2, 0xf0, 0x2d, 0xce, 0x6c, 0x2f, 0x4f, 0xf2,
         0xf5, 0x4f, 0xa5, 0xd4, 0x83, 0xad, 0x96, 0xa2, 0xf1, 0x87, 0x58, 0x04};
 
+// The Google ECDSA P256 root key for the Endpoint Encryption Key chain, encoded as COSE_Sign1
+inline constexpr uint8_t kCoseEncodedEcdsa256RootCert[] = {
+    0x84, 0x43, 0xa1, 0x01, 0x26, 0xa0, 0x58, 0x4d, 0xa5, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21,
+    0x58, 0x20, 0xf7, 0x14, 0x8a, 0xdb, 0x97, 0xf4, 0xcc, 0x53, 0xef, 0xd2, 0x64, 0x11, 0xc4, 0xe3,
+    0x75, 0x1f, 0x66, 0x1f, 0xa4, 0x71, 0x0c, 0x6c, 0xcf, 0xfa, 0x09, 0x46, 0x80, 0x74, 0x87, 0x54,
+    0xf2, 0xad, 0x22, 0x58, 0x20, 0x5e, 0x7f, 0x5b, 0xf6, 0xec, 0xe4, 0xf6, 0x19, 0xcc, 0xff, 0x13,
+    0x37, 0xfd, 0x0f, 0xa1, 0xc8, 0x93, 0xdb, 0x18, 0x06, 0x76, 0xc4, 0x5d, 0xe6, 0xd7, 0x6a, 0x77,
+    0x86, 0xc3, 0x2d, 0xaf, 0x8f, 0x58, 0x40, 0x2f, 0x97, 0x8e, 0x42, 0xfb, 0xbe, 0x07, 0x2d, 0x95,
+    0x47, 0x85, 0x47, 0x93, 0x40, 0xb0, 0x1f, 0xd4, 0x9b, 0x47, 0xa4, 0xc4, 0x44, 0xa9, 0xf2, 0xa1,
+    0x07, 0x87, 0x10, 0xc7, 0x9f, 0xcb, 0x11, 0xf4, 0xbf, 0x9f, 0xe8, 0x3b, 0xe0, 0xe7, 0x34, 0x4c,
+    0x15, 0xfc, 0x7b, 0xc3, 0x7e, 0x33, 0x05, 0xf4, 0xd1, 0x34, 0x3c, 0xed, 0x02, 0x04, 0x60, 0x7a,
+    0x15, 0xe0, 0x79, 0xd3, 0x8a, 0xff, 0x24};
+
+// The Google ECDSA P256 Endpoint Encryption Key certificate, encoded as COSE_Sign1
+inline constexpr uint8_t kCoseEncodedEcdsa256GeekCert[] = {
+    0x84, 0x43, 0xa1, 0x01, 0x26, 0xa0, 0x58, 0x71, 0xa6, 0x01, 0x02, 0x02, 0x58, 0x20, 0x35, 0x73,
+    0xb7, 0x3f, 0xa0, 0x8a, 0x80, 0x89, 0xb1, 0x26, 0x67, 0xe9, 0xcb, 0x7c, 0x75, 0xa1, 0xaf, 0x02,
+    0x61, 0xfc, 0x6e, 0x65, 0x03, 0x91, 0x3b, 0xd3, 0x4b, 0x7d, 0x14, 0x94, 0x3e, 0x46, 0x03, 0x38,
+    0x18, 0x20, 0x01, 0x21, 0x58, 0x20, 0xe0, 0x41, 0xcf, 0x2f, 0x0f, 0x34, 0x0f, 0x1c, 0x33, 0x2c,
+    0x41, 0xb0, 0xcf, 0xd7, 0x0c, 0x30, 0x55, 0x35, 0xd2, 0x1e, 0x6a, 0x47, 0x13, 0x4b, 0x2e, 0xd1,
+    0x48, 0x96, 0x7e, 0x24, 0x9c, 0x68, 0x22, 0x58, 0x20, 0x1f, 0xce, 0x45, 0xc5, 0xfb, 0x61, 0xba,
+    0x81, 0x21, 0xf9, 0xe5, 0x05, 0x9b, 0x9b, 0x39, 0x0e, 0x76, 0x86, 0x86, 0x47, 0xb8, 0x1e, 0x2f,
+    0x45, 0xf1, 0xce, 0xaf, 0xda, 0x3f, 0x80, 0x68, 0xdb, 0x58, 0x40, 0x8c, 0xb3, 0xba, 0x7e, 0x20,
+    0x3e, 0x32, 0xb0, 0x68, 0xdf, 0x60, 0xd1, 0x1d, 0x7d, 0xf0, 0xac, 0x38, 0x8e, 0x51, 0xbc, 0xff,
+    0x6c, 0xe1, 0x67, 0x3b, 0x4a, 0x79, 0xbc, 0x56, 0x78, 0xb3, 0x99, 0xd8, 0x7c, 0x8a, 0x07, 0xd8,
+    0xda, 0xb5, 0xb5, 0x7f, 0x71, 0xf4, 0xd8, 0x6b, 0xdf, 0x33, 0x27, 0x34, 0x7b, 0x65, 0xd1, 0x2a,
+    0xeb, 0x86, 0x99, 0x98, 0xab, 0x3a, 0xb4, 0x80, 0xaa, 0xbd, 0x50};
+
 /**
  * Generates random bytes.
  */
@@ -64,15 +92,15 @@
 };
 
 /**
- * Generates an X25518 EEK with the specified eekId and an Ed25519 chain of the
- * specified length. All keys are generated randomly.
+ * Based on the supportedEekCurve, Generates an X25519/ECDH with the specified eekId
+ * and an Ed25519/ECDSA chain of the specified length. All keys are generated randomly.
  */
-ErrMsgOr<EekChain> generateEekChain(size_t length, const bytevec& eekId);
+ErrMsgOr<EekChain> generateEekChain(int32_t supportedEekCurve, size_t length, const bytevec& eekId);
 
 /**
  * Returns the CBOR-encoded, production Google Endpoint Encryption Key chain.
  */
-bytevec getProdEekChain();
+bytevec getProdEekChain(int32_t supportedEekCurve);
 
 struct BccEntryData {
     bytevec pubKey;
@@ -96,17 +124,19 @@
 };
 
 /**
- * Take a given certificate request and output a JSON blob containing both the
- * build fingerprint and certificate request. This data may be serialized, then
- * later uploaded to the remote provisioning service. The input csr is not
- * validated, only encoded.
+ * Take a given instance name and certificate request, then output a JSON blob
+ * containing the name, build fingerprint and certificate request. This data may
+ * be serialized, then later uploaded to the remote provisioning service. The
+ * input csr is not validated, only encoded.
  *
  * Output format:
  *   {
  *     "build_fingerprint": <string>
  *     "csr": <base64 CBOR CSR>
+ *     "name": <string>
  *   }
  */
-JsonOutput jsonEncodeCsrWithBuild(const cppbor::Array& csr);
+JsonOutput jsonEncodeCsrWithBuild(const std::string instance_name,
+                                  const cppbor::Array& csr);
 
 }  // 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 0cbee51..0dbea5b 100644
--- a/security/keymint/support/remote_prov_utils.cpp
+++ b/security/keymint/support/remote_prov_utils.cpp
@@ -17,15 +17,186 @@
 #include <iterator>
 #include <tuple>
 
+#include <aidl/android/hardware/security/keymint/RpcHardwareInfo.h>
 #include <android-base/properties.h>
 #include <cppbor.h>
 #include <json/json.h>
+#include <keymaster/km_openssl/ec_key.h>
+#include <keymaster/km_openssl/ecdsa_operation.h>
+#include <keymaster/km_openssl/openssl_err.h>
+#include <keymaster/km_openssl/openssl_utils.h>
 #include <openssl/base64.h>
+#include <openssl/evp.h>
 #include <openssl/rand.h>
 #include <remote_prov/remote_prov_utils.h>
 
 namespace aidl::android::hardware::security::keymint::remote_prov {
 
+constexpr uint32_t kBccPayloadIssuer = 1;
+constexpr uint32_t kBccPayloadSubject = 2;
+constexpr int32_t kBccPayloadSubjPubKey = -4670552;
+constexpr int32_t kBccPayloadKeyUsage = -4670553;
+constexpr int kP256AffinePointSize = 32;
+
+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>;
+
+ErrMsgOr<bytevec> ecKeyGetPrivateKey(const EC_KEY* ecKey) {
+    // Extract private key.
+    const BIGNUM* bignum = EC_KEY_get0_private_key(ecKey);
+    if (bignum == nullptr) {
+        return "Error getting bignum from private key";
+    }
+    // Pad with zeros in case the length is lesser than 32.
+    bytevec privKey(32, 0);
+    BN_bn2binpad(bignum, privKey.data(), privKey.size());
+    return privKey;
+}
+
+ErrMsgOr<bytevec> ecKeyGetPublicKey(const EC_KEY* ecKey) {
+    // Extract public key.
+    auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
+    if (group.get() == nullptr) {
+        return "Error creating EC group by curve name";
+    }
+    const EC_POINT* point = EC_KEY_get0_public_key(ecKey);
+    if (point == nullptr) return "Error getting ecpoint from public key";
+
+    int size =
+        EC_POINT_point2oct(group.get(), point, POINT_CONVERSION_UNCOMPRESSED, nullptr, 0, nullptr);
+    if (size == 0) {
+        return "Error generating public key encoding";
+    }
+
+    bytevec publicKey;
+    publicKey.resize(size);
+    EC_POINT_point2oct(group.get(), point, POINT_CONVERSION_UNCOMPRESSED, publicKey.data(),
+                       publicKey.size(), nullptr);
+    return publicKey;
+}
+
+ErrMsgOr<std::tuple<bytevec, bytevec>> getAffineCoordinates(const bytevec& pubKey) {
+    auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
+    if (group.get() == nullptr) {
+        return "Error creating EC group by curve name";
+    }
+    auto point = EC_POINT_Ptr(EC_POINT_new(group.get()));
+    if (EC_POINT_oct2point(group.get(), point.get(), pubKey.data(), pubKey.size(), nullptr) != 1) {
+        return "Error decoding publicKey";
+    }
+    BIGNUM_Ptr x(BN_new());
+    BIGNUM_Ptr y(BN_new());
+    BN_CTX_Ptr ctx(BN_CTX_new());
+    if (!ctx.get()) return "Failed to create BN_CTX instance";
+
+    if (!EC_POINT_get_affine_coordinates_GFp(group.get(), point.get(), x.get(), y.get(),
+                                             ctx.get())) {
+        return "Failed to get affine coordinates from ECPoint";
+    }
+    bytevec pubX(kP256AffinePointSize);
+    bytevec pubY(kP256AffinePointSize);
+    if (BN_bn2binpad(x.get(), pubX.data(), kP256AffinePointSize) != kP256AffinePointSize) {
+        return "Error in converting absolute value of x coordinate to big-endian";
+    }
+    if (BN_bn2binpad(y.get(), pubY.data(), kP256AffinePointSize) != kP256AffinePointSize) {
+        return "Error in converting absolute value of y coordinate to big-endian";
+    }
+    return std::make_tuple(std::move(pubX), std::move(pubY));
+}
+
+ErrMsgOr<std::tuple<bytevec, bytevec>> generateEc256KeyPair() {
+    auto ec_key = EC_KEY_Ptr(EC_KEY_new());
+    if (ec_key.get() == nullptr) {
+        return "Failed to allocate ec key";
+    }
+
+    auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
+    if (group.get() == nullptr) {
+        return "Error creating EC group by curve name";
+    }
+
+    if (EC_KEY_set_group(ec_key.get(), group.get()) != 1 ||
+        EC_KEY_generate_key(ec_key.get()) != 1 || EC_KEY_check_key(ec_key.get()) < 0) {
+        return "Error generating key";
+    }
+
+    auto privKey = ecKeyGetPrivateKey(ec_key.get());
+    if (!privKey) return privKey.moveMessage();
+
+    auto pubKey = ecKeyGetPublicKey(ec_key.get());
+    if (!pubKey) return pubKey.moveMessage();
+
+    return std::make_tuple(pubKey.moveValue(), privKey.moveValue());
+}
+
+ErrMsgOr<std::tuple<bytevec, bytevec>> generateX25519KeyPair() {
+    /* Generate X25519 key pair */
+    bytevec pubKey(X25519_PUBLIC_VALUE_LEN);
+    bytevec privKey(X25519_PRIVATE_KEY_LEN);
+    X25519_keypair(pubKey.data(), privKey.data());
+    return std::make_tuple(std::move(pubKey), std::move(privKey));
+}
+
+ErrMsgOr<std::tuple<bytevec, bytevec>> generateED25519KeyPair() {
+    /* Generate ED25519 key pair */
+    bytevec pubKey(ED25519_PUBLIC_KEY_LEN);
+    bytevec privKey(ED25519_PRIVATE_KEY_LEN);
+    ED25519_keypair(pubKey.data(), privKey.data());
+    return std::make_tuple(std::move(pubKey), std::move(privKey));
+}
+
+ErrMsgOr<std::tuple<bytevec, bytevec>> generateKeyPair(int32_t supportedEekCurve, bool isEek) {
+    switch (supportedEekCurve) {
+    case RpcHardwareInfo::CURVE_25519:
+        if (isEek) {
+            return generateX25519KeyPair();
+        }
+        return generateED25519KeyPair();
+    case RpcHardwareInfo::CURVE_P256:
+        return generateEc256KeyPair();
+    default:
+        return "Unknown EEK Curve.";
+    }
+}
+
+ErrMsgOr<bytevec> constructCoseKey(int32_t supportedEekCurve, const bytevec& eekId,
+                                   const bytevec& pubKey) {
+    CoseKeyType keyType;
+    CoseKeyAlgorithm algorithm;
+    CoseKeyCurve curve;
+    bytevec pubX;
+    bytevec pubY;
+    switch (supportedEekCurve) {
+    case RpcHardwareInfo::CURVE_25519:
+        keyType = OCTET_KEY_PAIR;
+        algorithm = (eekId.empty()) ? EDDSA : ECDH_ES_HKDF_256;
+        curve = (eekId.empty()) ? ED25519 : cppcose::X25519;
+        pubX = pubKey;
+        break;
+    case RpcHardwareInfo::CURVE_P256: {
+        keyType = EC2;
+        algorithm = (eekId.empty()) ? ES256 : ECDH_ES_HKDF_256;
+        curve = P256;
+        auto affineCoordinates = getAffineCoordinates(pubKey);
+        if (!affineCoordinates) return affineCoordinates.moveMessage();
+        std::tie(pubX, pubY) = affineCoordinates.moveValue();
+    } break;
+    default:
+        return "Unknown EEK Curve.";
+    }
+    cppbor::Map coseKey = cppbor::Map()
+                              .add(CoseKey::KEY_TYPE, keyType)
+                              .add(CoseKey::ALGORITHM, algorithm)
+                              .add(CoseKey::CURVE, curve)
+                              .add(CoseKey::PUBKEY_X, pubX);
+
+    if (!pubY.empty()) coseKey.add(CoseKey::PUBKEY_Y, pubY);
+    if (!eekId.empty()) coseKey.add(CoseKey::KEY_ID, eekId);
+
+    return coseKey.canonicalize().encode();
+}
+
 bytevec kTestMacKey(32 /* count */, 0 /* byte value */);
 
 bytevec randomBytes(size_t numBytes) {
@@ -34,7 +205,17 @@
     return retval;
 }
 
-ErrMsgOr<EekChain> generateEekChain(size_t length, const bytevec& eekId) {
+ErrMsgOr<cppbor::Array> constructCoseSign1(int32_t supportedEekCurve, const bytevec& key,
+                                           const bytevec& payload, const bytevec& aad) {
+    if (supportedEekCurve == RpcHardwareInfo::CURVE_P256) {
+        return constructECDSACoseSign1(key, {} /* protectedParams */, payload, aad);
+    } else {
+        return cppcose::constructCoseSign1(key, payload, aad);
+    }
+}
+
+ErrMsgOr<EekChain> generateEekChain(int32_t supportedEekCurve, size_t length,
+                                    const bytevec& eekId) {
     if (length < 2) {
         return "EEK chain must contain at least 2 certs.";
     }
@@ -43,59 +224,74 @@
 
     bytevec prev_priv_key;
     for (size_t i = 0; i < length - 1; ++i) {
-        bytevec pub_key(ED25519_PUBLIC_KEY_LEN);
-        bytevec priv_key(ED25519_PRIVATE_KEY_LEN);
-
-        ED25519_keypair(pub_key.data(), priv_key.data());
+        auto keyPair = generateKeyPair(supportedEekCurve, false);
+        if (!keyPair) return keyPair.moveMessage();
+        auto [pub_key, priv_key] = keyPair.moveValue();
 
         // The first signing key is self-signed.
         if (prev_priv_key.empty()) prev_priv_key = priv_key;
 
-        auto coseSign1 = constructCoseSign1(prev_priv_key,
-                                            cppbor::Map() /* payload CoseKey */
-                                                    .add(CoseKey::KEY_TYPE, OCTET_KEY_PAIR)
-                                                    .add(CoseKey::ALGORITHM, EDDSA)
-                                                    .add(CoseKey::CURVE, ED25519)
-                                                    .add(CoseKey::PUBKEY_X, pub_key)
-                                                    .canonicalize()
-                                                    .encode(),
-                                            {} /* AAD */);
+        auto coseKey = constructCoseKey(supportedEekCurve, {}, pub_key);
+        if (!coseKey) return coseKey.moveMessage();
+
+        auto coseSign1 =
+            constructCoseSign1(supportedEekCurve, prev_priv_key, coseKey.moveValue(), {} /* AAD */);
         if (!coseSign1) return coseSign1.moveMessage();
         eekChain.add(coseSign1.moveValue());
 
         prev_priv_key = priv_key;
     }
+    auto keyPair = generateKeyPair(supportedEekCurve, true);
+    if (!keyPair) return keyPair.moveMessage();
+    auto [pub_key, priv_key] = keyPair.moveValue();
 
-    bytevec pub_key(X25519_PUBLIC_VALUE_LEN);
-    bytevec priv_key(X25519_PRIVATE_KEY_LEN);
-    X25519_keypair(pub_key.data(), priv_key.data());
+    auto coseKey = constructCoseKey(supportedEekCurve, eekId, pub_key);
+    if (!coseKey) return coseKey.moveMessage();
 
-    auto coseSign1 = constructCoseSign1(prev_priv_key,
-                                        cppbor::Map() /* payload CoseKey */
-                                                .add(CoseKey::KEY_TYPE, OCTET_KEY_PAIR)
-                                                .add(CoseKey::KEY_ID, eekId)
-                                                .add(CoseKey::ALGORITHM, ECDH_ES_HKDF_256)
-                                                .add(CoseKey::CURVE, cppcose::X25519)
-                                                .add(CoseKey::PUBKEY_X, pub_key)
-                                                .canonicalize()
-                                                .encode(),
-                                        {} /* AAD */);
+    auto coseSign1 =
+        constructCoseSign1(supportedEekCurve, prev_priv_key, coseKey.moveValue(), {} /* AAD */);
     if (!coseSign1) return coseSign1.moveMessage();
     eekChain.add(coseSign1.moveValue());
 
+    if (supportedEekCurve == RpcHardwareInfo::CURVE_P256) {
+        // convert ec public key to x and y co-ordinates.
+        auto affineCoordinates = getAffineCoordinates(pub_key);
+        if (!affineCoordinates) return affineCoordinates.moveMessage();
+        auto [pubX, pubY] = affineCoordinates.moveValue();
+        pub_key.clear();
+        pub_key.insert(pub_key.begin(), pubX.begin(), pubX.end());
+        pub_key.insert(pub_key.end(), pubY.begin(), pubY.end());
+    }
+
     return EekChain{eekChain.encode(), pub_key, priv_key};
 }
 
-bytevec getProdEekChain() {
-    bytevec prodEek;
-    prodEek.reserve(1 + sizeof(kCoseEncodedRootCert) + sizeof(kCoseEncodedGeekCert));
+bytevec getProdEekChain(int32_t supportedEekCurve) {
+    cppbor::Array chain;
+    if (supportedEekCurve == RpcHardwareInfo::CURVE_P256) {
+        chain.add(cppbor::EncodedItem(bytevec(std::begin(kCoseEncodedEcdsa256RootCert),
+                                              std::end(kCoseEncodedEcdsa256RootCert))));
+        chain.add(cppbor::EncodedItem(bytevec(std::begin(kCoseEncodedEcdsa256GeekCert),
+                                              std::end(kCoseEncodedEcdsa256GeekCert))));
+    } else {
+        chain.add(cppbor::EncodedItem(
+            bytevec(std::begin(kCoseEncodedRootCert), std::end(kCoseEncodedRootCert))));
+        chain.add(cppbor::EncodedItem(
+            bytevec(std::begin(kCoseEncodedGeekCert), std::end(kCoseEncodedGeekCert))));
+    }
+    return chain.encode();
+}
 
-    // In CBOR encoding, 0x82 indicates an array of two items
-    prodEek.push_back(0x82);
-    prodEek.insert(prodEek.end(), std::begin(kCoseEncodedRootCert), std::end(kCoseEncodedRootCert));
-    prodEek.insert(prodEek.end(), std::begin(kCoseEncodedGeekCert), std::end(kCoseEncodedGeekCert));
-
-    return prodEek;
+ErrMsgOr<bytevec> validatePayloadAndFetchPubKey(const cppbor::Map* payload) {
+    const auto& issuer = payload->get(kBccPayloadIssuer);
+    if (!issuer || !issuer->asTstr()) return "Issuer is not present or not a tstr.";
+    const auto& subject = payload->get(kBccPayloadSubject);
+    if (!subject || !subject->asTstr()) return "Subject is not present or not a tstr.";
+    const auto& keyUsage = payload->get(kBccPayloadKeyUsage);
+    if (!keyUsage || !keyUsage->asBstr()) return "Key usage is not present or not a bstr.";
+    const auto& serializedKey = payload->get(kBccPayloadSubjPubKey);
+    if (!serializedKey || !serializedKey->asBstr()) return "Key is not present or not a bstr.";
+    return serializedKey->asBstr()->value();
 }
 
 ErrMsgOr<bytevec> verifyAndParseCoseSign1Cwt(const cppbor::Array* coseSign1,
@@ -122,33 +318,53 @@
     }
 
     auto& algorithm = parsedProtParams->asMap()->get(ALGORITHM);
-    if (!algorithm || !algorithm->asInt() || algorithm->asInt()->value() != EDDSA) {
+    if (!algorithm || !algorithm->asInt() ||
+        (algorithm->asInt()->value() != EDDSA && algorithm->asInt()->value() != ES256)) {
         return "Unsupported signature algorithm";
     }
 
-    // TODO(jbires): Handle CWTs as the CoseSign1 payload in a less hacky way. Since the CWT payload
-    //               is extremely remote provisioning specific, probably just make a separate
-    //               function there.
     auto [parsedPayload, __, payloadErrMsg] = cppbor::parse(payload);
     if (!parsedPayload) return payloadErrMsg + " when parsing key";
     if (!parsedPayload->asMap()) return "CWT must be a map";
-    auto serializedKey = parsedPayload->asMap()->get(-4670552)->clone();
-    if (!serializedKey || !serializedKey->asBstr()) return "Could not find key entry";
-
-    bool selfSigned = signingCoseKey.empty();
-    auto key =
-            CoseKey::parseEd25519(selfSigned ? serializedKey->asBstr()->value() : signingCoseKey);
-    if (!key) return "Bad signing key: " + key.moveMessage();
-
-    bytevec signatureInput =
-            cppbor::Array().add("Signature1").add(*protectedParams).add(aad).add(*payload).encode();
-
-    if (!ED25519_verify(signatureInput.data(), signatureInput.size(), signature->value().data(),
-                        key->getBstrValue(CoseKey::PUBKEY_X)->data())) {
-        return "Signature verification failed";
+    auto serializedKey = validatePayloadAndFetchPubKey(parsedPayload->asMap());
+    if (!serializedKey) {
+        return "CWT validation failed: " + serializedKey.moveMessage();
     }
 
-    return serializedKey->asBstr()->value();
+    bool selfSigned = signingCoseKey.empty();
+    bytevec signatureInput =
+        cppbor::Array().add("Signature1").add(*protectedParams).add(aad).add(*payload).encode();
+
+    if (algorithm->asInt()->value() == EDDSA) {
+        auto key = CoseKey::parseEd25519(selfSigned ? *serializedKey : signingCoseKey);
+
+        if (!key) return "Bad signing key: " + key.moveMessage();
+
+        if (!ED25519_verify(signatureInput.data(), signatureInput.size(), signature->value().data(),
+                            key->getBstrValue(CoseKey::PUBKEY_X)->data())) {
+            return "Signature verification failed";
+        }
+    } else {  // P256
+        auto key = CoseKey::parseP256(selfSigned ? *serializedKey : signingCoseKey);
+        if (!key || key->getBstrValue(CoseKey::PUBKEY_X)->empty() ||
+            key->getBstrValue(CoseKey::PUBKEY_Y)->empty()) {
+            return "Bad signing key: " + key.moveMessage();
+        }
+        auto publicKey = key->getEcPublicKey();
+        if (!publicKey) return publicKey.moveMessage();
+
+        auto ecdsaDerSignature = ecdsaCoseSignatureToDer(signature->value());
+        if (!ecdsaDerSignature) return ecdsaDerSignature.moveMessage();
+
+        // convert public key to uncompressed form.
+        publicKey->insert(publicKey->begin(), 0x04);
+
+        if (!verifyEcdsaDigest(publicKey.moveValue(), sha256(signatureInput), *ecdsaDerSignature)) {
+            return "Signature verification failed";
+        }
+    }
+
+    return serializedKey.moveValue();
 }
 
 ErrMsgOr<std::vector<BccEntryData>> validateBcc(const cppbor::Array* bcc) {
@@ -156,8 +372,11 @@
 
     std::vector<BccEntryData> result;
 
+    const auto& devicePubKey = bcc->get(0);
+    if (!devicePubKey->asMap()) return "Invalid device public key at the 1st entry in the BCC";
+
     bytevec prevKey;
-    // TODO(jbires): Actually process the pubKey at the start of the new bcc entry
+
     for (size_t i = 1; i < bcc->size(); ++i) {
         const cppbor::Array* entry = bcc->get(i)->asArray();
         if (!entry || entry->size() != kCoseSign1EntryCount) {
@@ -177,12 +396,19 @@
 
         // This entry's public key is the signing key for the next entry.
         prevKey = payload.moveValue();
+        if (i == 1) {
+            auto [parsedRootKey, _, errMsg] = cppbor::parse(prevKey);
+            if (!parsedRootKey || !parsedRootKey->asMap()) return "Invalid payload entry in BCC.";
+            if (*parsedRootKey != *devicePubKey) {
+                return "Device public key doesn't match BCC root.";
+            }
+        }
     }
 
     return result;
 }
 
-JsonOutput jsonEncodeCsrWithBuild(const cppbor::Array& csr) {
+JsonOutput jsonEncodeCsrWithBuild(const std::string instance_name, const cppbor::Array& csr) {
     const std::string kFingerprintProp = "ro.build.fingerprint";
 
     if (!::android::base::WaitForPropertyCreation(kFingerprintProp)) {
@@ -206,6 +432,7 @@
     }
 
     Json::Value json(Json::objectValue);
+    json["name"] = instance_name;
     json["build_fingerprint"] = ::android::base::GetProperty(kFingerprintProp, /*default=*/"");
     json["csr"] = base64.data();  // Boring writes a NUL-terminated c-string
 
diff --git a/security/keymint/support/remote_prov_utils_test.cpp b/security/keymint/support/remote_prov_utils_test.cpp
index 8697c51..0250cd6 100644
--- a/security/keymint/support/remote_prov_utils_test.cpp
+++ b/security/keymint/support/remote_prov_utils_test.cpp
@@ -14,8 +14,12 @@
  * limitations under the License.
  */
 
+#include "cppbor.h"
+#include "keymaster/cppcose/cppcose.h"
+#include <aidl/android/hardware/security/keymint/RpcHardwareInfo.h>
 #include <android-base/properties.h>
 #include <cppbor_parse.h>
+#include <cstdint>
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 #include <keymaster/android_keymaster_utils.h>
@@ -23,25 +27,120 @@
 #include <keymaster/remote_provisioning_utils.h>
 #include <openssl/curve25519.h>
 #include <remote_prov/remote_prov_utils.h>
-#include <cstdint>
-#include "cppbor.h"
-#include "keymaster/cppcose/cppcose.h"
 
 namespace aidl::android::hardware::security::keymint::remote_prov {
 namespace {
 
 using ::keymaster::KeymasterBlob;
-using ::keymaster::validateAndExtractEekPubAndId;
+using ::keymaster::kStatusFailed;
+using ::keymaster::kStatusInvalidEek;
+using ::keymaster::StatusOr;
 using ::testing::ElementsAreArray;
+using byte_view = std::basic_string_view<uint8_t>;
+
+struct KeyInfoEcdsa {
+    CoseKeyCurve curve;
+    byte_view pubKeyX;
+    byte_view pubKeyY;
+
+    bool operator==(const KeyInfoEcdsa& other) const {
+        return curve == other.curve && pubKeyX == other.pubKeyX && pubKeyY == other.pubKeyY;
+    }
+};
+
+// The production root signing key for Google ECDSA P256 Endpoint Encryption Key cert chains.
+inline constexpr uint8_t kEcdsa256GeekRootX[] = {
+    0xf7, 0x14, 0x8a, 0xdb, 0x97, 0xf4, 0xcc, 0x53, 0xef, 0xd2, 0x64, 0x11, 0xc4, 0xe3, 0x75, 0x1f,
+    0x66, 0x1f, 0xa4, 0x71, 0x0c, 0x6c, 0xcf, 0xfa, 0x09, 0x46, 0x80, 0x74, 0x87, 0x54, 0xf2, 0xad};
+
+inline constexpr uint8_t kEcdsa256GeekRootY[] = {
+    0x5e, 0x7f, 0x5b, 0xf6, 0xec, 0xe4, 0xf6, 0x19, 0xcc, 0xff, 0x13, 0x37, 0xfd, 0x0f, 0xa1, 0xc8,
+    0x93, 0xdb, 0x18, 0x06, 0x76, 0xc4, 0x5d, 0xe6, 0xd7, 0x6a, 0x77, 0x86, 0xc3, 0x2d, 0xaf, 0x8f};
+
+// Hard-coded set of acceptable public COSE_Keys that can act as roots of EEK chains.
+inline constexpr KeyInfoEcdsa kAuthorizedEcdsa256EekRoots[] = {
+    {CoseKeyCurve::P256, byte_view(kEcdsa256GeekRootX, sizeof(kEcdsa256GeekRootX)),
+     byte_view(kEcdsa256GeekRootY, sizeof(kEcdsa256GeekRootY))},
+};
+
+static ErrMsgOr<CoseKey> parseEcdh256(const bytevec& coseKey) {
+    auto key = CoseKey::parse(coseKey, EC2, ECDH_ES_HKDF_256, P256);
+    if (!key) return key;
+
+    auto& pubkey_x = key->getMap().get(cppcose::CoseKey::PUBKEY_X);
+    auto& pubkey_y = key->getMap().get(cppcose::CoseKey::PUBKEY_Y);
+    if (!pubkey_x || !pubkey_y || !pubkey_x->asBstr() || !pubkey_y->asBstr() ||
+        pubkey_x->asBstr()->value().size() != 32 || pubkey_y->asBstr()->value().size() != 32) {
+        return "Invalid P256 public key";
+    }
+
+    return key;
+}
+
+StatusOr<std::tuple<std::vector<uint8_t> /* EEK pubX */, std::vector<uint8_t> /* EEK pubY */,
+                    std::vector<uint8_t> /* EEK ID */>>
+validateAndExtractEcdsa256EekPubAndId(bool testMode,
+                                      const KeymasterBlob& endpointEncryptionCertChain) {
+    auto [item, newPos, errMsg] =
+        cppbor::parse(endpointEncryptionCertChain.begin(), endpointEncryptionCertChain.end());
+    if (!item || !item->asArray()) {
+        return kStatusFailed;
+    }
+    const cppbor::Array* certArr = item->asArray();
+    std::vector<uint8_t> lastPubKey;
+    for (size_t i = 0; i < certArr->size(); ++i) {
+        auto cosePubKey =
+            verifyAndParseCoseSign1(certArr->get(i)->asArray(), lastPubKey, {} /* AAD */);
+        if (!cosePubKey) {
+            return kStatusInvalidEek;
+        }
+        lastPubKey = *std::move(cosePubKey);
+
+        // In prod mode the first pubkey should match a well-known Google public key.
+        if (!testMode && i == 0) {
+            auto parsedPubKey = CoseKey::parse(lastPubKey);
+            if (!parsedPubKey) {
+                return kStatusFailed;
+            }
+            auto curve = parsedPubKey->getIntValue(CoseKey::CURVE);
+            if (!curve) {
+                return kStatusInvalidEek;
+            }
+            auto rawPubX = parsedPubKey->getBstrValue(CoseKey::PUBKEY_X);
+            if (!rawPubX) {
+                return kStatusInvalidEek;
+            }
+            auto rawPubY = parsedPubKey->getBstrValue(CoseKey::PUBKEY_Y);
+            if (!rawPubY) {
+                return kStatusInvalidEek;
+            }
+            KeyInfoEcdsa matcher = {static_cast<CoseKeyCurve>(*curve),
+                                    byte_view(rawPubX->data(), rawPubX->size()),
+                                    byte_view(rawPubY->data(), rawPubY->size())};
+            if (std::find(std::begin(kAuthorizedEcdsa256EekRoots),
+                          std::end(kAuthorizedEcdsa256EekRoots),
+                          matcher) == std::end(kAuthorizedEcdsa256EekRoots)) {
+                return kStatusInvalidEek;
+            }
+        }
+    }
+    auto eek = parseEcdh256(lastPubKey);
+    if (!eek) {
+        return kStatusInvalidEek;
+    }
+    return std::make_tuple(eek->getBstrValue(CoseKey::PUBKEY_X).value(),
+                           eek->getBstrValue(CoseKey::PUBKEY_Y).value(),
+                           eek->getBstrValue(CoseKey::KEY_ID).value());
+}
 
 TEST(RemoteProvUtilsTest, GenerateEekChainInvalidLength) {
-    ASSERT_FALSE(generateEekChain(1, /*eekId=*/{}));
+    ASSERT_FALSE(generateEekChain(RpcHardwareInfo::CURVE_25519, 1, /*eekId=*/{}));
 }
 
 TEST(RemoteProvUtilsTest, GenerateEekChain) {
     bytevec kTestEekId = {'t', 'e', 's', 't', 'I', 'd', 0};
     for (size_t length : {2, 3, 31}) {
-        auto get_eek_result = generateEekChain(length, kTestEekId);
+        auto get_eek_result = generateEekChain(RpcHardwareInfo::CURVE_25519, length, kTestEekId);
         ASSERT_TRUE(get_eek_result) << get_eek_result.message();
 
         auto& [chain, pubkey, privkey] = *get_eek_result;
@@ -57,7 +156,7 @@
 }
 
 TEST(RemoteProvUtilsTest, GetProdEekChain) {
-    auto chain = getProdEekChain();
+    auto chain = getProdEekChain(RpcHardwareInfo::CURVE_25519);
 
     auto validation_result = validateAndExtractEekPubAndId(
             /*testMode=*/false, KeymasterBlob(chain.data(), chain.size()));
@@ -86,16 +185,68 @@
     cppbor::Array array;
     array.add(1);
 
-    auto [json, error] = jsonEncodeCsrWithBuild(array);
+    auto [json, error] = jsonEncodeCsrWithBuild(std::string("test"), array);
 
     ASSERT_TRUE(error.empty()) << error;
 
     std::string expected = R"({"build_fingerprint":")" +
                            ::android::base::GetProperty("ro.build.fingerprint", /*default=*/"") +
-                           R"(","csr":"gQE="})";
+                           R"(","csr":"gQE=","name":"test"})";
 
     ASSERT_EQ(json, expected);
 }
 
+TEST(RemoteProvUtilsTest, GenerateEcdsaEekChainInvalidLength) {
+    ASSERT_FALSE(generateEekChain(RpcHardwareInfo::CURVE_P256, 1, /*eekId=*/{}));
+}
+
+TEST(RemoteProvUtilsTest, GenerateEcdsaEekChain) {
+    bytevec kTestEekId = {'t', 'e', 's', 't', 'I', 'd', 0};
+    for (size_t length : {2, 3, 31}) {
+        auto get_eek_result = generateEekChain(RpcHardwareInfo::CURVE_P256, length, kTestEekId);
+        ASSERT_TRUE(get_eek_result) << get_eek_result.message();
+
+        auto& [chain, pubkey, privkey] = *get_eek_result;
+
+        auto validation_result = validateAndExtractEcdsa256EekPubAndId(
+            /*testMode=*/true, KeymasterBlob(chain.data(), chain.size()));
+        ASSERT_TRUE(validation_result.isOk());
+
+        auto& [eekPubX, eekPubY, eekId] = *validation_result;
+        bytevec eekPub;
+        eekPub.insert(eekPub.begin(), eekPubX.begin(), eekPubX.end());
+        eekPub.insert(eekPub.end(), eekPubY.begin(), eekPubY.end());
+        EXPECT_THAT(eekId, ElementsAreArray(kTestEekId));
+        EXPECT_THAT(eekPub, ElementsAreArray(pubkey));
+    }
+}
+
+TEST(RemoteProvUtilsTest, GetProdEcdsaEekChain) {
+    auto chain = getProdEekChain(RpcHardwareInfo::CURVE_P256);
+
+    auto validation_result = validateAndExtractEcdsa256EekPubAndId(
+        /*testMode=*/false, KeymasterBlob(chain.data(), chain.size()));
+    ASSERT_TRUE(validation_result.isOk()) << "Error: " << validation_result.moveError();
+
+    auto& [eekPubX, eekPubY, eekId] = *validation_result;
+
+    auto [geekCert, ignoredNewPos, error] =
+        cppbor::parse(kCoseEncodedEcdsa256GeekCert, sizeof(kCoseEncodedEcdsa256GeekCert));
+    ASSERT_NE(geekCert, nullptr) << "Error: " << error;
+    ASSERT_NE(geekCert->asArray(), nullptr);
+
+    auto& encodedGeekCoseKey = geekCert->asArray()->get(kCoseSign1Payload);
+    ASSERT_NE(encodedGeekCoseKey, nullptr);
+    ASSERT_NE(encodedGeekCoseKey->asBstr(), nullptr);
+
+    auto geek = CoseKey::parse(encodedGeekCoseKey->asBstr()->value());
+    ASSERT_TRUE(geek) << "Error: " << geek.message();
+
+    const std::vector<uint8_t> empty;
+    EXPECT_THAT(eekId, ElementsAreArray(geek->getBstrValue(CoseKey::KEY_ID).value_or(empty)));
+    EXPECT_THAT(eekPubX, ElementsAreArray(geek->getBstrValue(CoseKey::PUBKEY_X).value_or(empty)));
+    EXPECT_THAT(eekPubY, ElementsAreArray(geek->getBstrValue(CoseKey::PUBKEY_Y).value_or(empty)));
+}
+
 }  // namespace
 }  // namespace aidl::android::hardware::security::keymint::remote_prov
diff --git a/security/secureclock/aidl/Android.bp b/security/secureclock/aidl/Android.bp
index b70dda9..00a6ba3 100644
--- a/security/secureclock/aidl/Android.bp
+++ b/security/secureclock/aidl/Android.bp
@@ -17,7 +17,6 @@
     backend: {
         java: {
             platform_apis: true,
-            srcs_available: true,
         },
         ndk: {
             vndk: {
@@ -26,6 +25,10 @@
         },
         rust: {
             enabled: true,
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.compos",
+            ],
         },
     },
     versions: ["1"],
diff --git a/security/secureclock/aidl/OWNERS b/security/secureclock/aidl/OWNERS
deleted file mode 100644
index a93b171..0000000
--- a/security/secureclock/aidl/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-jbires@google.com
-jdanis@google.com
-seleneh@google.com
-swillden@google.com
diff --git a/security/secureclock/aidl/android/hardware/security/secureclock/ISecureClock.aidl b/security/secureclock/aidl/android/hardware/security/secureclock/ISecureClock.aidl
index a742ff0..e6d63c8 100644
--- a/security/secureclock/aidl/android/hardware/security/secureclock/ISecureClock.aidl
+++ b/security/secureclock/aidl/android/hardware/security/secureclock/ISecureClock.aidl
@@ -25,6 +25,10 @@
  * secret. The shared secret must be available to secure clock service by implementing
  * ISharedSecret aidl. Note: ISecureClock depends on the shared secret, without which the secure
  * time stamp token cannot be generated.
+ *
+ * The timer must be the same that is used for HardwareAuthTokens. The ISecureClock interface is
+ * used to convey a fresh timestamp to those components that do not share a timer with the
+ * authenticators.
  * @hide
  */
 @VintfStability
diff --git a/security/secureclock/aidl/android/hardware/security/secureclock/TimeStampToken.aidl b/security/secureclock/aidl/android/hardware/security/secureclock/TimeStampToken.aidl
index 2fbd29a..fcf2ee8 100644
--- a/security/secureclock/aidl/android/hardware/security/secureclock/TimeStampToken.aidl
+++ b/security/secureclock/aidl/android/hardware/security/secureclock/TimeStampToken.aidl
@@ -39,7 +39,7 @@
      * 32-byte HMAC-SHA256 of the above values, computed as:
      *
      *    HMAC(H,
-     *         ISecureClock.TIME_STAMP_MAC_LABEL || challenge || timestamp || securityLevel )
+     *         ISecureClock.TIME_STAMP_MAC_LABEL || challenge || timestamp || 1 )
      *
      * where:
      *
@@ -50,9 +50,7 @@
      *   ``||'' represents concatenation
      *
      * The representation of challenge and timestamp is as 64-bit unsigned integers in big-endian
-     * order. SecurityLevel is represented as a 32-bit unsigned integer in big-endian order as
-     * described in android.hardware.security.keymint.SecurityLevel. It represents the security
-     * level of the secure clock environment.
+     * order.  1, above, is a 32-bit unsigned integer, also big-endian.
      */
     byte[] mac;
 }
diff --git a/security/secureclock/aidl/vts/functional/Android.bp b/security/secureclock/aidl/vts/functional/Android.bp
index 56c8e1d..a34668b 100644
--- a/security/secureclock/aidl/vts/functional/Android.bp
+++ b/security/secureclock/aidl/vts/functional/Android.bp
@@ -27,6 +27,7 @@
     name: "VtsAidlSecureClockTargetTest",
     defaults: [
         "VtsHalTargetTestDefaults",
+        "keymint_use_latest_hal_aidl_ndk_static",
         "use_libaidlvintf_gtest_helper_static",
     ],
     cflags: [
@@ -41,8 +42,7 @@
         "libcrypto",
     ],
     static_libs: [
-        "android.hardware.security.keymint-V1-ndk_platform",
-        "android.hardware.security.secureclock-V1-ndk_platform",
+        "android.hardware.security.secureclock-V1-ndk",
         "libkeymint",
     ],
     test_suites: [
diff --git a/security/sharedsecret/aidl/OWNERS b/security/sharedsecret/aidl/OWNERS
deleted file mode 100644
index a93b171..0000000
--- a/security/sharedsecret/aidl/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-jbires@google.com
-jdanis@google.com
-seleneh@google.com
-swillden@google.com
diff --git a/security/sharedsecret/aidl/vts/functional/Android.bp b/security/sharedsecret/aidl/vts/functional/Android.bp
index d3747fc..1f0f6a6 100644
--- a/security/sharedsecret/aidl/vts/functional/Android.bp
+++ b/security/sharedsecret/aidl/vts/functional/Android.bp
@@ -27,6 +27,7 @@
     name: "VtsAidlSharedSecretTargetTest",
     defaults: [
         "VtsHalTargetTestDefaults",
+        "keymint_use_latest_hal_aidl_ndk_static",
         "use_libaidlvintf_gtest_helper_static",
     ],
     srcs: [
@@ -41,8 +42,7 @@
         "libcrypto",
     ],
     static_libs: [
-        "android.hardware.security.keymint-V1-ndk_platform",
-        "android.hardware.security.sharedsecret-V1-ndk_platform",
+        "android.hardware.security.sharedsecret-V1-ndk",
         "libkeymint",
     ],
     test_suites: [
diff --git a/sensors/1.0/vts/functional/Android.bp b/sensors/1.0/vts/functional/Android.bp
index 9a92fb3..274cfa7 100644
--- a/sensors/1.0/vts/functional/Android.bp
+++ b/sensors/1.0/vts/functional/Android.bp
@@ -27,6 +27,9 @@
     name: "VtsHalSensorsV1_0TargetTest",
     cflags: ["-DLOG_TAG=\"sensors_hidl_hal_test\""],
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: [
+        "VtsHalSensorsV1_0TargetTest.cpp",
+    ],
     srcs: [
         "SensorsHidlEnvironmentV1_0.cpp",
         "VtsHalSensorsV1_0TargetTest.cpp",
diff --git a/sensors/1.0/vts/functional/OWNERS b/sensors/1.0/vts/functional/OWNERS
index 892da15..e20125b 100644
--- a/sensors/1.0/vts/functional/OWNERS
+++ b/sensors/1.0/vts/functional/OWNERS
@@ -1,8 +1,2 @@
-# Sensors team
-arthuri@google.com
-bduddie@google.com
-stange@google.com
-
-# VTS team
-trong@google.com
-yim@google.com
+# Bug component: 62965
+include ../../../common/vts/OWNERS
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 0b3d4c2..8867a1a 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
@@ -2,6 +2,6 @@
     class hal
     user system
     group system wakelock context_hub
-    writepid /dev/cpuset/system-background/tasks
+    task_profiles ServiceCapacityLow
     capabilities BLOCK_SUSPEND
     rlimit rtprio 10 10
diff --git a/sensors/2.0/vts/functional/Android.bp b/sensors/2.0/vts/functional/Android.bp
index cf7c9fa..c4ec866 100644
--- a/sensors/2.0/vts/functional/Android.bp
+++ b/sensors/2.0/vts/functional/Android.bp
@@ -27,6 +27,9 @@
     name: "VtsHalSensorsV2_0TargetTest",
     cflags: ["-DLOG_TAG=\"sensors_hidl_hal_test\""],
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: [
+        "VtsHalSensorsV2_0TargetTest.cpp",
+    ],
     srcs: [
         "VtsHalSensorsV2_0TargetTest.cpp",
     ],
diff --git a/sensors/2.0/vts/functional/OWNERS b/sensors/2.0/vts/functional/OWNERS
index 892da15..e20125b 100644
--- a/sensors/2.0/vts/functional/OWNERS
+++ b/sensors/2.0/vts/functional/OWNERS
@@ -1,8 +1,2 @@
-# Sensors team
-arthuri@google.com
-bduddie@google.com
-stange@google.com
-
-# VTS team
-trong@google.com
-yim@google.com
+# Bug component: 62965
+include ../../../common/vts/OWNERS
diff --git a/sensors/2.1/default/Android.bp b/sensors/2.1/default/Android.bp
index 0be81e1..e11316b 100644
--- a/sensors/2.1/default/Android.bp
+++ b/sensors/2.1/default/Android.bp
@@ -22,6 +22,11 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
+filegroup {
+    name: "android.hardware.sensors@2.1.xml",
+    srcs: ["android.hardware.sensors@2.1.xml"],
+}
+
 cc_binary {
     name: "android.hardware.sensors@2.1-service.mock",
     defaults: ["hidl_defaults"],
@@ -50,5 +55,5 @@
         "android.hardware.sensors@1.0-convert",
         "android.hardware.sensors@2.X-shared-impl",
     ],
-    vintf_fragments: ["android.hardware.sensors@2.1.xml"],
+    vintf_fragments: [":android.hardware.sensors@2.1.xml"],
 }
diff --git a/sensors/2.1/default/apex/Android.bp b/sensors/2.1/default/apex/Android.bp
new file mode 100644
index 0000000..3345b92
--- /dev/null
+++ b/sensors/2.1/default/apex/Android.bp
@@ -0,0 +1,46 @@
+package {
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+apex_key {
+    name: "com.android.hardware.sensors.key",
+    public_key: "com.android.hardware.sensors.avbpubkey",
+    private_key: "com.android.hardware.sensors.pem",
+}
+
+android_app_certificate {
+    name: "com.android.hardware.sensors.certificate",
+    certificate: "com.android.hardware.sensors",
+}
+
+prebuilt_etc {
+    name: "com.android.hardware.sensors.rc",
+    src: "com.android.hardware.sensors.rc",
+    installable: false,
+}
+
+// Default vendor APEX for android.hardware.sensors.
+// Custom implementations may use override_apex based on this APEX.
+apex {
+    name: "com.android.hardware.sensors",
+    manifest: "apex_manifest.json",
+    key: "com.android.hardware.sensors.key",
+    certificate: ":com.android.hardware.sensors.certificate",
+    file_contexts: "file_contexts",
+    use_vndk_as_stable: true,
+    updatable: false,
+    // Install the apex in /vendor/apex
+    soc_specific: true,
+    binaries: ["android.hardware.sensors@2.1-service.mock"],
+    prebuilts: [
+        "com.android.hardware.sensors.rc",
+        "android.hardware.sensor.ambient_temperature.prebuilt.xml",
+        "android.hardware.sensor.barometer.prebuilt.xml",
+        "android.hardware.sensor.gyroscope.prebuilt.xml",
+        "android.hardware.sensor.hinge_angle.prebuilt.xml",
+        "android.hardware.sensor.light.prebuilt.xml",
+        "android.hardware.sensor.proximity.prebuilt.xml",
+        "android.hardware.sensor.relative_humidity.prebuilt.xml",
+    ],
+    vintf_fragments: [":android.hardware.sensors@2.1.xml"],
+}
diff --git a/sensors/2.1/default/apex/apex_manifest.json b/sensors/2.1/default/apex/apex_manifest.json
new file mode 100644
index 0000000..47e45ee
--- /dev/null
+++ b/sensors/2.1/default/apex/apex_manifest.json
@@ -0,0 +1,4 @@
+{
+  "name": "com.android.hardware.sensors",
+  "version": 1
+}
diff --git a/sensors/2.1/default/apex/com.android.hardware.sensors.avbpubkey b/sensors/2.1/default/apex/com.android.hardware.sensors.avbpubkey
new file mode 100644
index 0000000..98dfb71
--- /dev/null
+++ b/sensors/2.1/default/apex/com.android.hardware.sensors.avbpubkey
Binary files differ
diff --git a/sensors/2.1/default/apex/com.android.hardware.sensors.pem b/sensors/2.1/default/apex/com.android.hardware.sensors.pem
new file mode 100644
index 0000000..a2f1833
--- /dev/null
+++ b/sensors/2.1/default/apex/com.android.hardware.sensors.pem
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIJKAIBAAKCAgEArUwl9rjXtNrSqJ2rfEryTnVEte7uhZlsn42rXRHFZtuV8N03
+AKAFDDkhJIT+FqmVJLW1Whrno+goaKzA23BodZcSo/xOJuTopgQ/TVqIO2QZ2WUS
+1NiYT3+kydZgtBHhfS+ek9h6aTLgJUn/XBX2xgEA6kp/NkcLpGkqj9Xs7XUpG+n/
+KnyYg+/YFqooEKHTTi4dT9YgRblgzv5zhCKxjB9gqy8dmhwDTpbPGavNiMIZvnSs
+aQzXh7+UMwte+V4QdaEqonoVWm85vEh6rsPpvvmxvlkVnUstRWRwsvbA183gvwZg
+f7OmAgpVu0kEkSHpoJJWpDUhzxmTdxmwvmL92eCJqQUjvxLqak4uBt+epUgbgxcA
+nS7rNg6PsNlHhYl5wRArPP17iW/QK3qnoz8rKgJCtdxPPD13byA13eY9q+Fdwb2H
+uHxGu1iYlRxUAzptvb6pIED/v9MMw/g3yMJkR89WG+pBLbUXHko6H0qOVchYrd8C
+OtcGo7GBBPbJmj9ZGZDX7p5YBSdTZs8f9wWqJmXkfVR60zZE0dOnOchzL44c8oUh
+uwEZMee7Ae/2LfWnfIe5KBNTvvH1CzU8KbQUJJVbATbb3j/eYExgsbnk0WgFi6i4
+osuJZZmfC44tAg18gXozcji+xYuW3MIMV2+drdc3xXn7LXKn5JZCLVJ6n+cCAwEA
+AQKCAgATT6P/XVO0NJo67e75F8Tul0TD3U85FgKzuO66nUtZDekkgRIrAKnvVcJq
+tmM2FUmoYJNH6i2b5zfxiianjVwmlmIeYfQ3g1Slg12megsqSxpSTmAN1eELItcz
+Iq9+AWwWLiNGqF3jsSanIRrSoSPxppT6hrisTLhwZsO2aYlQYLjnAmlLy7yXHzf+
+NpHmYJISaTMc/Wh1PJYcGuC2fcM5MRntmX9799kqfcWwP6PUtIR347p+rk6qMuAJ
+3B+GPEQrR31fw6jzfed6Ir2BEhXPETYMVxMAhysRS4L/fl247pk30Dcao+NA4PPy
+vc1Devr0yLnc7IrK8DetkvBOFuvgl53gHPZ4f7ge2PQMPghwjBaFuXklcfY96PVw
+Yo/CyAN+VEANThFFcKUzovtHI6m3sNTlxE6F+AYvx5dE/WZKmE5/cYCSJ8bhLPJl
+G68VkdeNv0LMZ/7rf1OEWP/YWw/5/tQ7MJ0IO5GShjE2EAGG0SZgK8/fwHZZJFES
+oYVWlriGtGDfiYjPLqVIjdZI6iOo6BMQh6pl0TPIJpn3ODqtRy8gN3TMvG6VcTJy
+QE3Z+br7UsK4gXSw0+MNLC3VKhX2bjT5q9lVpVnLv4L7q1ad4kwHblFAo686ZbWt
+eKTUv7QTI3fFqYeZEgCqRBQZ3UoKyWOBg0MAbf26hZFTFFpbEQKCAQEA2JdW6wDM
+iO1haR168l497nUC382/f/fJA8vzFdJ7cHVM95Tx/5JNYNJSL30XDyux9RJNqnFu
+tByec4c5CVuX/Gv/B4Q++xaaI7OVT9hTl/aoTShObGRJGbVh8xZagb7on7dAfD6G
+1SzTaahxQT5neoiki13GvJ6teL+0ZbCxRDMfPyy79lRzH5d0mw+EQvtc0Vvkweyj
+zf/Mn0yMZHO19oCKjJo8QkciseOqaS2mpgtOiRDc01uuaFAcw6taiERrR86xK2Yl
+OowIx6Yu8n7jRyTGUfr2Oz97a/zDVMVRi3BuyePOyCD9PfUmoj9JyCFbQSS1Lq3N
+AWacnNwQpkDDiQKCAQEAzNQ3/hKhjrLyEm2ktQk1Tzyk4eGu/NElxSKM7uJTeU0k
+xxKuMNMQCJbZmklJKojVYZ0fsh6AyLEpBMV6mWTmVo0qA/A09jKD2tsKu52KGCMt
+vgrN4Gi5JJJACNbtpG7uSJstAYuUGYQSTuS/xCE+urgMVbWBTocsf0bEeEe0FRWX
+txhS/zdj6wspTd6lJ0SSahWG/BsV7990zaRDGYv0N1+SwF8/C0Ml99WbyRof6oP9
+jx0esKA+giWc5lSk+Ag2gpsTIH36aF53lQnDBZL3hqSgqP0ollKa9Uyjfmp65D1m
+TwoENrKnVNO5ZKteTM3SGQ+zsHxBPpinK7T2BPe77wKCAQBdS+Nu2ys/mDErnD1H
+hXzb6J9SVEg3ET8PWZzeO4pciMqcoxYS5qxaFn68Yf+60zGWxUmbL71l7CX80bSp
+6UBwxPxX+ok+kx/WXRbmC+MGRIN+qOwPGKu8XTtSAMD/voJpugAXBMADt4lhq+MN
+HZppV865Ea33tco3hyxn2VKic/rztYtJslrcstrRqD9qsufqbtD9D7gHljZIMCsR
+Yh5xjjEgG5f1XLr/MXhIUhfE0n4D4LWefZGE8W1Sg889f2tOxSPf8+H5dDSb+2Oh
+pTK1hIvA6H+ESfYaMAjbzRsxGz89y9lYr40mUSFRJj3b7TJnvy4ka00xW0f+8XRi
+iOcxAoIBAB0o8Te4i0t3akL5XQNw5if7qDWIHZNcaxYfjxTLH7sbIms825OT2KqA
+X0Y5vLLTfB1Dcym2cfsgTYiiXIvN84TK3/pjjgamtmLH4EVJbkl1aKOvghO6lPEB
+6R/ZCUfpiv7HKKcZqeHgDYMxyaMwYG/Ql+Dz0A7P66PK/VlqS9bclha43cf7qLvj
+gOPXGIf4mSeFHQxzBrJ5i3VjNzJB3GitsIS2ipEd5B/eRylgEL8gP07KhH38silx
+FV8tGbc95BS/4v8zMBz/peKP2zXF8Hs4oK6uK8MKy4i0emoa2pf3rcL+2A65bF0F
+L1WHmAszGf/7Xkd3yQoSTWpJfuTCJ/0CggEBAJjkBaEoiRYp0RBq1Ty0wa+xbPHp
+gAcpco+VC3T8uqniKBDrf5QsMDm7+P9IZRYrfgyy0KFeG4mHrTt61JgOLnhSTOyz
+EEChc8SOn6+vqMB36FmSSqVb6CdLEZhv5dtTzzHgyd3xS3cwga9Mf2SCoG/l34HJ
+XzfoQyLKvqF0kWOq/76k+kBM5QwWIGc2fVXcpJpWaAuPWKDQJnkvTcPp8XPyEADv
+z2YbSDDqqcwczX2DWepf2t2RU1fdyjS5wS6pNDvsuyd6gwUTQT1P5ODHbIdAwcdi
+5Gxui8voJmzvrfabIsN6H73ZS4Lw20ZB+ejYyiwxZcb0os45C1coicMJ9wQ=
+-----END RSA PRIVATE KEY-----
diff --git a/sensors/2.1/default/apex/com.android.hardware.sensors.pk8 b/sensors/2.1/default/apex/com.android.hardware.sensors.pk8
new file mode 100644
index 0000000..7a1cca0
--- /dev/null
+++ b/sensors/2.1/default/apex/com.android.hardware.sensors.pk8
Binary files differ
diff --git a/sensors/2.1/default/apex/com.android.hardware.sensors.rc b/sensors/2.1/default/apex/com.android.hardware.sensors.rc
new file mode 100644
index 0000000..bd245b4
--- /dev/null
+++ b/sensors/2.1/default/apex/com.android.hardware.sensors.rc
@@ -0,0 +1,7 @@
+service vendor.sensors-hal-2-1-mock /apex/com.android.hardware.sensors/bin/hw/android.hardware.sensors@2.1-service.mock
+    interface android.hardware.sensors@2.0::ISensors default
+    interface android.hardware.sensors@2.1::ISensors default
+    class hal
+    user system
+    group system
+    rlimit rtprio 10 10
diff --git a/sensors/2.1/default/apex/com.android.hardware.sensors.x509.pem b/sensors/2.1/default/apex/com.android.hardware.sensors.x509.pem
new file mode 100644
index 0000000..20a06f9
--- /dev/null
+++ b/sensors/2.1/default/apex/com.android.hardware.sensors.x509.pem
@@ -0,0 +1,34 @@
+-----BEGIN CERTIFICATE-----
+MIIF3TCCA8UCFAbIl4RS714WSLo4k64MHsINz4VEMA0GCSqGSIb3DQEBCwUAMIGp
+MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
+bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
+MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTElMCMGA1UEAwwcY29t
+LmFuZHJvaWQuaGFyZHdhcmUuc2Vuc29yczAgFw0yMTA5MDMxNjEyNDNaGA80NzU5
+MDczMTE2MTI0M1owgakxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh
+MRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYD
+VQQLDAdBbmRyb2lkMSIwIAYJKoZIhvcNAQkBFhNhbmRyb2lkQGFuZHJvaWQuY29t
+MSUwIwYDVQQDDBxjb20uYW5kcm9pZC5oYXJkd2FyZS5zZW5zb3JzMIICIjANBgkq
+hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnluNTPcq4pDEeb5gEYszRYQCawq8czUY
+J+x2b0i7qO2wLidX45CX6BLZ9N7c5veoV3FvC1wMTRR6lGAyg7UbD80vVmPdmr6R
+vw2AdIqrghXinvAEv6gxQQPVQa8UHkCL4lULLXo2gdmoCBM8VJHihjO/2F8ZLsP/
+nKhYx9Nr6w9LEyalmHTkXOgNyrNprpbJwugdk3hDXbAK+j5nF9fsz/iWFoXnPuNe
+oqdWj21YhXKDAbewBXaM6l3qmTdGsVVJL4HmVURGUY2f2UZwMWTEjpy9UDzyfqqg
+CSdH1RLmGVAINyfNI3Zswo0CjnOCf0jW6mq9/6mfGYu8hBCrky/rOH8reDwYZTGe
+H6JbNj0dhEN5HzQcxGEQQ43L1nmH7XlnuPO0xPSsw5binPVuUvURivR3PSsFgpPl
+0Uche62XgLAXCXhNV2uUQtZLVFGug7JcGgS4O3GoKr6w35Q+W9SEXanXFMW6X+wN
+hkbhB4MDSuKTZrjEnZEyxMOLG8ILN9i7osa+yjWONTn9bZc6q3Y9jyu3u84o8kC8
+KDcvr8YZEL63nQsQXO44GiQmqBptuB+ehcAC6uRCKkY9tQ95EQ7laGQ3C85d3gPj
+NcGjT7SSuUir7n+LI9pZsotedd9+rGhiiyT8CM4sVWiYJFnA2UX/bsnkZyAOq9Po
+jz1aMdHc4wUCAwEAATANBgkqhkiG9w0BAQsFAAOCAgEATEPN2SZk8pJc4DaWmhyR
+MUklzVeuN0J0Mij1mHuVmID7Q5IhBBXxtVmwRIo208rHSvFLAo7Z4FnuZCV3A/c9
+TlXT3S2t+iYG5eOyXSsoSc/uerJ7kIBcOe27qIrO9GwcK5CQlTaXP+CG1gbLp1nl
+IaqKAT+eb/ji5wmFxMI77wo3uKLPTCfpaptFNaYlRqvxiXdJsCZwCPgmCtXJUeeZ
+R/HKOA4PcS2QB+HwhYePY5kUJPwt6MwJEyno72oenfl49FrGHj0BzVmQ7KMfiYjZ
+eRSB2Wbo50xfiICkPlUcvWD8rRNg7N9CM/Q5O0MW3ivAe42aGap/8qfXUa+L5vu4
+9vaxgQvBVcPXE/pyeCYM8beB84Us+FOYPC7gIUhcctBqGYAQmHzp3sXvIg0DVxz7
+0aqolFGpjRFqbgheS9WRkDHFpYrhR1XMVOQjussHqWEyRcvliqeFlZr8+JNkJNi+
+lmGMdnEAWZs8PL0/AEf+8y0Nr/w0k3Y6IZCDcwpxbpJQOU5pAbkfUzEJHkxMfuvW
+ZshvqIMOaLWCGxZaxlbLRxWGuarWYzfmDY3n9TwJmAIUdMLiswv3UsCmLBJO1XGX
+SUWfgi4fyG1/phfzhdU3efMvmN+XT16/ykMrY8P5S+ghwK12IZ3DgTl0ooLFABUj
+zYeQ8LLz3SP9LNgeLnPP/po=
+-----END CERTIFICATE-----
diff --git a/sensors/2.1/default/apex/file_contexts b/sensors/2.1/default/apex/file_contexts
new file mode 100644
index 0000000..d0095c0
--- /dev/null
+++ b/sensors/2.1/default/apex/file_contexts
@@ -0,0 +1,5 @@
+(/.*)?							u:object_r:vendor_file:s0
+# Permission XMLs
+/etc/permissions(/.*)?					u:object_r:vendor_configs_file:s0
+# Service binary
+/bin/hw/android\.hardware\.sensors@2\.1-service\.mock	u:object_r:hal_sensors_default_exec:s0
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 fc99ee7..f47e060 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
@@ -2,6 +2,6 @@
     class hal
     user system
     group system wakelock context_hub
-    writepid /dev/cpuset/system-background/tasks
+    task_profiles ServiceCapacityLow
     capabilities BLOCK_SUSPEND
     rlimit rtprio 10 10
diff --git a/sensors/2.1/vts/functional/OWNERS b/sensors/2.1/vts/functional/OWNERS
index 892da15..e20125b 100644
--- a/sensors/2.1/vts/functional/OWNERS
+++ b/sensors/2.1/vts/functional/OWNERS
@@ -1,8 +1,2 @@
-# Sensors team
-arthuri@google.com
-bduddie@google.com
-stange@google.com
-
-# VTS team
-trong@google.com
-yim@google.com
+# Bug component: 62965
+include ../../../common/vts/OWNERS
diff --git a/sensors/common/default/2.X/Sensor.cpp b/sensors/common/default/2.X/Sensor.cpp
index 1a7c628..fd701fd 100644
--- a/sensors/common/default/2.X/Sensor.cpp
+++ b/sensors/common/default/2.X/Sensor.cpp
@@ -59,10 +59,10 @@
 }
 
 void Sensor::batch(int64_t samplingPeriodNs) {
-    if (samplingPeriodNs < mSensorInfo.minDelay * 1000ll) {
-        samplingPeriodNs = mSensorInfo.minDelay * 1000ll;
-    } else if (samplingPeriodNs > mSensorInfo.maxDelay * 1000ll) {
-        samplingPeriodNs = mSensorInfo.maxDelay * 1000ll;
+    if (samplingPeriodNs < mSensorInfo.minDelay * 1000LL) {
+        samplingPeriodNs = mSensorInfo.minDelay * 1000LL;
+    } else if (samplingPeriodNs > mSensorInfo.maxDelay * 1000LL) {
+        samplingPeriodNs = mSensorInfo.maxDelay * 1000LL;
     }
 
     if (mSamplingPeriodNs != samplingPeriodNs) {
@@ -114,7 +114,7 @@
             });
         } else {
             timespec curTime;
-            clock_gettime(CLOCK_REALTIME, &curTime);
+            clock_gettime(CLOCK_BOOTTIME, &curTime);
             int64_t now = (curTime.tv_sec * kNanosecondsInSeconds) + curTime.tv_nsec;
             int64_t nextSampleTime = mLastSampleTimeNs + mSamplingPeriodNs;
 
diff --git a/sensors/common/default/2.X/multihal/HalProxy.cpp b/sensors/common/default/2.X/multihal/HalProxy.cpp
index f5fc066..ccc4172 100644
--- a/sensors/common/default/2.X/multihal/HalProxy.cpp
+++ b/sensors/common/default/2.X/multihal/HalProxy.cpp
@@ -250,8 +250,8 @@
         Result currRes = mSubHalList[i]->initialize(this, this, i);
         if (currRes != Result::OK) {
             result = currRes;
-            ALOGE("Subhal '%s' failed to initialize.", mSubHalList[i]->getName().c_str());
-            break;
+            ALOGE("Subhal '%s' failed to initialize with reason %" PRId32 ".",
+                  mSubHalList[i]->getName().c_str(), static_cast<int32_t>(currRes));
         }
     }
 
diff --git a/sensors/common/default/2.X/multihal/HalProxyCallback.cpp b/sensors/common/default/2.X/multihal/HalProxyCallback.cpp
index 3c1b17c..addefe8 100644
--- a/sensors/common/default/2.X/multihal/HalProxyCallback.cpp
+++ b/sensors/common/default/2.X/multihal/HalProxyCallback.cpp
@@ -68,6 +68,10 @@
     std::vector<V2_1::Event> eventsOut;
     for (V2_1::Event event : events) {
         event.sensorHandle = setSubHalIndex(event.sensorHandle, mSubHalIndex);
+        if (event.sensorType == V2_1::SensorType::DYNAMIC_SENSOR_META) {
+            event.u.dynamic.sensorHandle =
+                    setSubHalIndex(event.u.dynamic.sensorHandle, mSubHalIndex);
+        }
         eventsOut.push_back(event);
         const V2_1::SensorInfo& sensor = mCallback->getSensorInfo(event.sensorHandle);
         if ((sensor.flags & V1_0::SensorFlagBits::WAKE_UP) != 0) {
diff --git a/sensors/common/default/2.X/multihal/tests/Android.bp b/sensors/common/default/2.X/multihal/tests/Android.bp
index d8e7ce6..21d1d77 100644
--- a/sensors/common/default/2.X/multihal/tests/Android.bp
+++ b/sensors/common/default/2.X/multihal/tests/Android.bp
@@ -99,6 +99,9 @@
 
 cc_test {
     name: "android.hardware.sensors@2.X-halproxy-unit-tests",
+    tidy_timeout_srcs: [
+        "HalProxy_test.cpp",
+    ],
     srcs: [
         "HalProxy_test.cpp",
         "ScopedWakelock_test.cpp",
diff --git a/sensors/common/default/2.X/multihal/tests/fake_subhal/Sensor.cpp b/sensors/common/default/2.X/multihal/tests/fake_subhal/Sensor.cpp
index 69debb6..f5745c5 100644
--- a/sensors/common/default/2.X/multihal/tests/fake_subhal/Sensor.cpp
+++ b/sensors/common/default/2.X/multihal/tests/fake_subhal/Sensor.cpp
@@ -125,7 +125,7 @@
             });
         } else {
             timespec curTime;
-            clock_gettime(CLOCK_REALTIME, &curTime);
+            clock_gettime(CLOCK_BOOTTIME, &curTime);
             int64_t now = (curTime.tv_sec * kNanosecondsInSeconds) + curTime.tv_nsec;
             int64_t nextSampleTime = mLastSampleTimeNs + mSamplingPeriodNs;
 
diff --git a/sensors/common/vts/OWNERS b/sensors/common/vts/OWNERS
index 892da15..1b9a2f8 100644
--- a/sensors/common/vts/OWNERS
+++ b/sensors/common/vts/OWNERS
@@ -1,8 +1,5 @@
+# Bug component: 62965
 # Sensors team
 arthuri@google.com
 bduddie@google.com
 stange@google.com
-
-# VTS team
-trong@google.com
-yim@google.com
diff --git a/soundtrigger/2.0/vts/functional/OWNERS b/soundtrigger/2.0/vts/functional/OWNERS
new file mode 100644
index 0000000..3c24468
--- /dev/null
+++ b/soundtrigger/2.0/vts/functional/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 48436
+elaurent@google.com
+mdooley@google.com
+ytai@google.com
diff --git a/soundtrigger/2.1/vts/functional/OWNERS b/soundtrigger/2.1/vts/functional/OWNERS
new file mode 100644
index 0000000..3c24468
--- /dev/null
+++ b/soundtrigger/2.1/vts/functional/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 48436
+elaurent@google.com
+mdooley@google.com
+ytai@google.com
diff --git a/soundtrigger/2.2/vts/functional/OWNERS b/soundtrigger/2.2/vts/functional/OWNERS
new file mode 100644
index 0000000..43126f6
--- /dev/null
+++ b/soundtrigger/2.2/vts/functional/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 48436
+ytai@google.com
+mdooley@google.com
diff --git a/soundtrigger/2.3/vts/functional/OWNERS b/soundtrigger/2.3/vts/functional/OWNERS
new file mode 100644
index 0000000..3c24468
--- /dev/null
+++ b/soundtrigger/2.3/vts/functional/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 48436
+elaurent@google.com
+mdooley@google.com
+ytai@google.com
diff --git a/tests/extension/vibrator/aidl/client/Android.bp b/tests/extension/vibrator/aidl/client/Android.bp
index afab263..284ac74 100644
--- a/tests/extension/vibrator/aidl/client/Android.bp
+++ b/tests/extension/vibrator/aidl/client/Android.bp
@@ -27,7 +27,7 @@
         "android.hardware.tests.extension.vibrator-V1-cpp",
 
         "libbinder_ndk",
-        "android.hardware.vibrator-V2-ndk_platform",
-        "android.hardware.tests.extension.vibrator-V1-ndk_platform",
+        "android.hardware.vibrator-V2-ndk",
+        "android.hardware.tests.extension.vibrator-V1-ndk",
     ],
 }
diff --git a/tests/extension/vibrator/aidl/default/Android.bp b/tests/extension/vibrator/aidl/default/Android.bp
index a200292..0f3895f 100644
--- a/tests/extension/vibrator/aidl/default/Android.bp
+++ b/tests/extension/vibrator/aidl/default/Android.bp
@@ -28,7 +28,7 @@
     shared_libs: [
         "libbase",
         "libbinder_ndk",
-        "android.hardware.vibrator-V2-ndk_platform",
-        "android.hardware.tests.extension.vibrator-V2-ndk_platform",
+        "android.hardware.vibrator-V2-ndk",
+        "android.hardware.tests.extension.vibrator-V2-ndk",
     ],
 }
diff --git a/tests/lazy_cb/1.0/.hidl_for_system_ext b/tests/lazy_cb/1.0/.hidl_for_system_ext
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/lazy_cb/1.0/.hidl_for_system_ext
diff --git a/tests/lazy_cb/1.0/Android.bp b/tests/lazy_cb/1.0/Android.bp
new file mode 100644
index 0000000..4d82b63
--- /dev/null
+++ b/tests/lazy_cb/1.0/Android.bp
@@ -0,0 +1,23 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+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"],
+}
+
+hidl_interface {
+    name: "android.hardware.tests.lazy_cb@1.0",
+    root: "android.hardware",
+    system_ext_specific: true,
+    srcs: [
+        "ILazyCb.hal",
+    ],
+    interfaces: [
+        "android.hidl.base@1.0",
+    ],
+    gen_java: true,
+}
diff --git a/tests/lazy_cb/1.0/ILazyCb.hal b/tests/lazy_cb/1.0/ILazyCb.hal
new file mode 100644
index 0000000..a9046b3
--- /dev/null
+++ b/tests/lazy_cb/1.0/ILazyCb.hal
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tests.lazy_cb@1.0;
+
+interface ILazyCb {
+    /**
+     * Set the eventfd used to notify that the active services
+     * callback is being executed and is about to terminate the process.
+     */
+    setEventFd(handle fds) generates (bool success);
+};
diff --git a/tests/msgq/1.0/default/Android.bp b/tests/msgq/1.0/default/Android.bp
index 5f116e7..75973fc 100644
--- a/tests/msgq/1.0/default/Android.bp
+++ b/tests/msgq/1.0/default/Android.bp
@@ -100,10 +100,10 @@
     // These are static libs only for testing purposes and portability. Shared
     // libs should be used on device.
     static_libs: [
-        "android.hardware.common-V2-ndk_platform",
-        "android.hardware.common.fmq-V1-ndk_platform",
+        "android.hardware.common-V2-ndk",
+        "android.hardware.common.fmq-V1-ndk",
         "android.hardware.tests.msgq@1.0",
-        "android.fmq.test-ndk_platform",
+        "android.fmq.test-ndk",
     ],
     whole_static_libs: [
         "android.hardware.tests.msgq@1.0-impl",
diff --git a/thermal/1.0/vts/functional/OWNERS b/thermal/1.0/vts/functional/OWNERS
new file mode 100644
index 0000000..0c282a0
--- /dev/null
+++ b/thermal/1.0/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 623506
+wvw@google.com
diff --git a/thermal/2.0/default/Android.bp b/thermal/2.0/default/Android.bp
index a63ffbc..f743ade 100644
--- a/thermal/2.0/default/Android.bp
+++ b/thermal/2.0/default/Android.bp
@@ -22,16 +22,26 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
+filegroup {
+    name: "android.hardware.thermal@2.0-service.xml",
+    srcs: ["android.hardware.thermal@2.0-service.xml"],
+}
+
+filegroup {
+    name: "android.hardware.thermal@2.0-service.rc",
+    srcs: ["android.hardware.thermal@2.0-service.rc"],
+}
+
 cc_binary {
     name: "android.hardware.thermal@2.0-service.mock",
     defaults: ["hidl_defaults"],
     relative_install_path: "hw",
     vendor: true,
-    init_rc: ["android.hardware.thermal@2.0-service.rc"],
-    vintf_fragments: ["android.hardware.thermal@2.0-service.xml"],
+    init_rc: [":android.hardware.thermal@2.0-service.rc"],
+    vintf_fragments: [":android.hardware.thermal@2.0-service.xml"],
     srcs: [
         "Thermal.cpp",
-        "service.cpp"
+        "service.cpp",
     ],
     shared_libs: [
         "libbase",
diff --git a/thermal/2.0/default/apex/Android.bp b/thermal/2.0/default/apex/Android.bp
new file mode 100644
index 0000000..914a3a8
--- /dev/null
+++ b/thermal/2.0/default/apex/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 {
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+apex_key {
+    name: "com.android.hardware.thermal.key",
+    public_key: "com.android.hardware.thermal.avbpubkey",
+    private_key: "com.android.hardware.thermal.pem",
+}
+
+android_app_certificate {
+    name: "com.android.hardware.thermal.certificate",
+    certificate: "com.android.hardware.thermal",
+}
+
+genrule {
+    name: "com.android.hardware.thermal.rc-gen",
+    srcs: [":android.hardware.thermal@2.0-service.rc"],
+    out: ["com.android.hardware.thermal.rc"],
+    cmd: "sed -E 's/\\/vendor/\\/apex\\/com.android.hardware.thermal.mock/' $(in) > $(out)",
+}
+
+prebuilt_etc {
+    name: "com.android.hardware.thermal.rc",
+    src: ":com.android.hardware.thermal.rc-gen",
+    installable: false,
+}
+
+apex {
+    name: "com.android.hardware.thermal.mock",
+    manifest: "manifest.json",
+    file_contexts: "file_contexts",
+    key: "com.android.hardware.thermal.key",
+    certificate: ":com.android.hardware.thermal.certificate",
+    use_vndk_as_stable: true,
+    updatable: false,
+    soc_specific: true,
+    binaries: ["android.hardware.thermal@2.0-service.mock"],
+    prebuilts: ["com.android.hardware.thermal.rc"],
+    vintf_fragments: [":android.hardware.thermal@2.0-service.xml"],
+}
diff --git a/thermal/2.0/default/apex/com.android.hardware.thermal.avbpubkey b/thermal/2.0/default/apex/com.android.hardware.thermal.avbpubkey
new file mode 100644
index 0000000..8f7cf72
--- /dev/null
+++ b/thermal/2.0/default/apex/com.android.hardware.thermal.avbpubkey
Binary files differ
diff --git a/thermal/2.0/default/apex/com.android.hardware.thermal.pem b/thermal/2.0/default/apex/com.android.hardware.thermal.pem
new file mode 100644
index 0000000..4ea6e85
--- /dev/null
+++ b/thermal/2.0/default/apex/com.android.hardware.thermal.pem
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIJKQIBAAKCAgEApXL2prEKqnU/xHlYeZB55x5EOrVAsfBuyHN5xOgUY877UuDC
+xoX+DOYAkCDSwMPmBj/Q9E70lId1PXMeI3y0obgYpdFubqRsoGNcEq2zG811tr6J
+BAE/7mAI0a4VVFWtauBNTiP5G31hsRpZNTE/dyZxs20GEVQqdvtBlEAuebCt7VIb
+fCwXnPCXSiYQ9WyjU0dwHoZPuy02qBuq3v9NYt5J6lYiPDqTWmpYBFm+SIZvth/j
+HUcaU3p+BlUad0qLhA8HYTPPBwJq2uHbTXeFrWXngt+UPCdzYubyUjG4WmgHIfee
+zSvoTjud2Gaofnd4/PcE5jFTMYUJuz0D4E+8StZArw+xegfxGcvqFZ4gfKAO1Vha
+eQBhw94P2eieUfh9metQEyKZ+A24sxG0awtAUOgcwr/WNv2TgJoN8+56DhuPXOuO
+U2qeIZuIrmE5xmyzrzJsCx+5vRQA7A3kpxRo1ZCgbJlzMgdAQaRTe2rqxyyoeFQR
+HbxUdsM7ZwDLE62UlaTTZFoJ1wzvZmsIJdkdRg97zcc3R3kYnVehCxAZ1KdAKzq6
+bhrw/kNAVA0zUHhlhHWGDnJQ/rkGfjQ9GGhS51IJYgKEoQc5M9hSgZD3idic8hso
+63r/P2Wn4S78gwLigfpzsGD7RrusTbMIRkebwpHwAYpB8qIykrtUKfunLtMCAwEA
+AQKCAgEAjiKbv0ytaw9bfwD4f0cdUu5vkzgPok55/f8mh4ERs0UoKGUrL74BKTeX
+GDr6k9w4CvpcGuaRu+A7WlVBeR8zVxN/KUUo6CidoZR6jxlmm+YA0MQTlbs1Hyal
+rO0vKcqJNx4Hi6/f3Dv0519JcCck7Mm8OHbbFZwG9zyXdDNHOggNA6rcLer7Rjpy
+3qKhQxbXoT3oFnEwog8Pu5A5VWZjJyLswULKGo//81cU0nf+vvOvmPj/9jEVbs32
+4p3OJNmHziXTIzCNFOqAvhX2fzDFSNgY8hf9k0gZGshpOS+5vwFLz2SZqo2j/0G8
+MyLOcgdVi4zzSobpf8tZNuAOKnCVwxteV3Ddl0o+qAf4cQCAXtuEkJvFWpAxrX4m
+J7nDDuvcTjKMlnchlm6XxmP27YNTKA2w5uNfrJQV5LR3IDs77PFpNiKOwERka6MU
+WE1LnjAFTCDxujT29NfIjC9z0iOY45TYut4okesaK7woe6pfK2H0ouvE6mZ+Lb7Y
+qZphPb4e4DZZZAVoELVvWflm/VC/xmBMA9vtzpjuvRXD+iYjgxbHaiG2UANLWmTd
+vADLqBadlbp10AvyrjKxHUhAiZnJgaVKRXtw5qk8YrwZOwypEHCQjY41fJuRScWF
+pD58/PYOLtSdwewzTijXSVwwPeqL1JMdJ+KWFk5zI410DtmHwoECggEBANM5dHEj
+L4ZOCcgHVG7aCLah7f/0Za7BBiPsZFD0uRIzWFTd77st3v8ulMw1JQiO3+xmpL7e
+iOP+onuSEMKgNQqeX9WCnv6pL+mjg0of2IEcGnvCpmfUZRA2x/MlyJRrQ1vHGqkV
+oBIIWgCGmIAWuFbHPmkNYx7mAJymAfzShkVtMw29oiGYyubqx9cTjD0odeyScbhZ
+LuMt72O5QeNsPREX4SsSRAL+vZbz1+8iRI8Fon89csZym3hos3DA4QSml+FNHnLe
+YFD6AfU7pdn79YhhNkn4jE0BxLaEkXhMs8RRTU2Q3o990ZxrAZGQz4zqOm5sOIQT
+JaXFXxGvOwEysrMCggEBAMiFaTzkhJSLEmLEu0T3gNEC2d3jE9kt4Olv4mQmzD00
+AzDtkrkArLQCeG3CMn55oFcJRwr8gAEk7/f2mvJSoZQnw0J0tRI+QiHJG4zwdsQC
+UszqN89X8ef0yoobwVa31ZoWxK4/NvLO4GZQ6UUd9uni10jfYVWmwEwKBU61ihvT
+ntcZIXvROR6khxzLeXtglnsznnYcdYMPJUeN+cfK9/rL3V3jk1jes8y8XwYfxkUa
+99nEe1NkRCUznzKxvkRwnKunlMCEkZ5z4nNMlqEqiOlVEYgwKwNCP+qM7ZKUJg7t
+uOL91bqWFPj2qdzyUh0uP5V/dg2odnu0xSblKWhxI2ECggEBAKbZttJ8Idlsoath
+pt+d2c4yoadTLlNZ5HjSDfgpKFxpNLhtTCbGuGVJLX8V5/gXrGi4OCER9n5rMXx9
+SEIFfYCy1C77bI7rpI5hfJ88ArESOxVSEFLqYx7otw+p5AThqibAY533GCfGcxoB
+OEvOJrVd1D31tju9IfSb6ewFfM0w0mhjSMRTRswb39pUda4F3QkQMUaXJEOOkJBs
+0dBNOvvaqiJ03kajZa3tVsBuiEuV/uOV7ak29Pqrcjt6EQW0dzsgyRGh+eFda9iE
+0qEbt7uQVusdq+5UnEg09hhaNpK4SmEgM76Te9WcbXPIOTst9xQs5oPmABIvk8aL
+bgenPaMCggEAX9EAHIzFnYVm37NKGQZ7k2RdXt2nGlwF4QYJk/nGFmjILZUYSza7
+T7jueuQU5MKRj4VrYSCOuf1AfahlGe3KL9VgRF0oOPNu/l3uwEYXOkox7qDs0jMf
+8MrUDXJ9zEZD10GR8gFa7GNWbw2yqchLuC8g2D2FcTwhHzSanKW6vNk+SWJE0bmE
+JdRQi73e6smYnn5n9eBbdqjCE5MQDBw8qqbHvJmGSyz/lZFdhrugLl1YmcJ9e7ep
+qG0mYT71wBZfhtapCeVO//w39Qhf4dtFWNnBauY5Z3E8wYNd8nDATtnhQvYwLtyQ
+YPbc7CsOecsjrvgdHSGmnC4hFxjh1HpbgQKCAQBzEr35CFQpUfGsu06SqRrxp7mb
+BfQzLmqnt+ZLu21H/YjVbamMXNjbJFSdtFLxAK/s9vFGQzEWWEYia2pRZejlCXhQ
+RO+TREJ4rm4Erfdh+zS9z8MZlxe2ybIMs260XxjZ0gEltRtJ6P14zLBlChi/rQEY
+tGrOpfjvLc1Lryaucwj7snDLtMfyqvemAUmuJNn/6IEMuG4DcdtJ3Whh7t3xKfO0
+Hc71Oh7F30okQQ6Ctiwp1T77Y1EXlRJrUtpf1sLxeItP6/r3WXLNaiFdKqGJxiCM
+Gw11oUcBA9bvfAzeJIpVVbLtGPNOp4J1XpkgFcWzsTM+ZpxWwbj4yJL6rSN2
+-----END RSA PRIVATE KEY-----
diff --git a/thermal/2.0/default/apex/com.android.hardware.thermal.pk8 b/thermal/2.0/default/apex/com.android.hardware.thermal.pk8
new file mode 100644
index 0000000..3e5bf69
--- /dev/null
+++ b/thermal/2.0/default/apex/com.android.hardware.thermal.pk8
Binary files differ
diff --git a/thermal/2.0/default/apex/com.android.hardware.thermal.x509.pem b/thermal/2.0/default/apex/com.android.hardware.thermal.x509.pem
new file mode 100644
index 0000000..048e69a
--- /dev/null
+++ b/thermal/2.0/default/apex/com.android.hardware.thermal.x509.pem
@@ -0,0 +1,34 @@
+-----BEGIN CERTIFICATE-----
+MIIF3TCCA8UCFFWeg2KJX/fyAqZPcKaFS61/a3GiMA0GCSqGSIb3DQEBCwUAMIGp
+MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
+bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
+MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTElMCMGA1UEAwwcY29t
+LmFuZHJvaWQuaGFyZHdhcmUudGhlcm1hbDAgFw0yMTExMTcxODE3MjRaGA80NzU5
+MTAxNDE4MTcyNFowgakxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh
+MRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYD
+VQQLDAdBbmRyb2lkMSIwIAYJKoZIhvcNAQkBFhNhbmRyb2lkQGFuZHJvaWQuY29t
+MSUwIwYDVQQDDBxjb20uYW5kcm9pZC5oYXJkd2FyZS50aGVybWFsMIICIjANBgkq
+hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA2W8QhCKX0WoS5jhIWbWBoKulD6XhKASA
+CL0oU6Uci0U6id2m++ou/T0aHSlliS9kT1NEABNwbLeTDa9h1qg1lbajRzXbvzEz
+EvZYT+dlgYFNZ9zaVCIlMapoiN+nrM/Rs24UBjJrZu1B39+IcE5ciQz69PgrLKWF
+vFEdYzxWI246azOVr3fvdelQg+CyPgiGObVAGOHhAidvsjg4FssKnADzn+JNlTt6
+b9P65xUQErut8hz9YdLtfZ096iwe8eEpsMOQwCNdKNXVCcNjQWkOwRaU+0awHoH1
+4mArvF7yyvJxqzkNaR03BPqXAHPIAPu6xdfA19+HVIiz6bLEZ1mfCM6edXByCWZu
+K8o54OZph71r15ncv4DVd+cnBjNvBvfdlJSeGjSreFkUo5NkfAwqdmLfZx6CedHI
+sLx7X8vPYolQnR4UEvaX6yeNN0gs8Dd6ePMqOEiwWFVASD+cbpcUrp09uzlDStGV
+1DPx/9J2kw8eXPMqOSGThkLWuUMUFojyh7bNlL16oYmEeZW6/OOXCOXzAQgJ7NIs
+DA1/H2w1HMHWgSfF4y+Es2CiqcgVFOIU/07b31Edw4v56pjx1CUpRpJZjDA1JJNo
+A4YCnpA6JWTxzUTmv21fEYyY+poA3CuzvCfZ80z9h/UFW98oM9GawGvK0i2pLudS
+RaZXWeil08cCAwEAATANBgkqhkiG9w0BAQsFAAOCAgEAj2gpn/IpAHQLDlI52WwL
+IDc5uzlf1BGseLZ8M8uuMiwvN00nOjunQQZEIbhH7+03GYyMzRhTTI3nWwmX4Fnq
+vC5sR68yNlu9gOAMXaAHo/Rw73ak7sv8xGbb2FeQsHaMKDQ2nqxP17SWdQ0xWa1u
+5qNurPOdAPOw77noZcT7yYX7lcrOKxPIekPJxyeOlp4bQSmabSRgYr70B7GybPlv
+K1gkgCBxl5RiVjVxLo+7ESHSAaGLy0S7F2v6PJ9oj15TovWQ0py2iBKZ6HReB7s/
+umnQqkwXDLudlNmoXIsgIYn8vKFTYpy1GSNJqhRSLfvLR6NtuU0iCTvg/X7oPmS1
+dWUdjVeO7ZVvIpO3gLLEe4maBEYF2sOlt3bRmzIHydORJtkfTt5tiZ4wR9RfJbkj
+iBiDbNiX010bZPTAXmgMbuJzQXZEXCBy0qKeS1cHwf9M8FDoiLajXepfZIp+6syt
+D4lZk4eAV141JL5PfABfdZWwT3cTgFIqCYpqrMQJIu+GHEjUwD2yNPi0I1/ydFCW
+CPDnzWjYCi6yVB8hss3ZFbvhfyJzdm3LivNVbLGK0+TG0EOAz6d2aQ0UjESgMD1A
+U8hLzQt7MiFSG0bt2cVx6SgCHeYUqMntbFELEAURWrhAfPLMJtAvFgKbEiZEAkkW
+pdDVh603aIp4LjVCfTYp/mQ=
+-----END CERTIFICATE-----
diff --git a/thermal/2.0/default/apex/file_contexts b/thermal/2.0/default/apex/file_contexts
new file mode 100644
index 0000000..e0d87c7
--- /dev/null
+++ b/thermal/2.0/default/apex/file_contexts
@@ -0,0 +1,5 @@
+(/.*)?                                                    u:object_r:vendor_file:s0
+# Permission XMLs
+/etc/permissions(/.*)?                                    u:object_r:vendor_configs_file:s0
+# binary
+/bin/hw/android\.hardware\.thermal@2\.0-service\.mock     u:object_r:hal_thermal_default_exec:s0
diff --git a/thermal/2.0/default/apex/manifest.json b/thermal/2.0/default/apex/manifest.json
new file mode 100644
index 0000000..ee44dc1
--- /dev/null
+++ b/thermal/2.0/default/apex/manifest.json
@@ -0,0 +1,4 @@
+{
+  "name": "com.android.hardware.thermal.mock",
+  "version": 1
+}
diff --git a/thermal/2.0/vts/functional/Android.bp b/thermal/2.0/vts/functional/Android.bp
index f26c1af..29dffcb 100644
--- a/thermal/2.0/vts/functional/Android.bp
+++ b/thermal/2.0/vts/functional/Android.bp
@@ -26,6 +26,7 @@
 cc_test {
     name: "VtsHalThermalV2_0TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: ["VtsHalThermalV2_0TargetTest.cpp"],
     srcs: ["VtsHalThermalV2_0TargetTest.cpp"],
     static_libs: [
         "android.hardware.thermal@1.0",
diff --git a/thermal/2.0/vts/functional/OWNERS b/thermal/2.0/vts/functional/OWNERS
new file mode 100644
index 0000000..0c282a0
--- /dev/null
+++ b/thermal/2.0/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 623506
+wvw@google.com
diff --git a/thermal/2.0/vts/functional/VtsHalThermalV2_0TargetTest.cpp b/thermal/2.0/vts/functional/VtsHalThermalV2_0TargetTest.cpp
index 6c5aca7..c7bab5c 100644
--- a/thermal/2.0/vts/functional/VtsHalThermalV2_0TargetTest.cpp
+++ b/thermal/2.0/vts/functional/VtsHalThermalV2_0TargetTest.cpp
@@ -103,8 +103,6 @@
 
 // Test ThermalChangedCallback::notifyThrottling().
 // This just calls into and back from our local ThermalChangedCallback impl.
-// Note: a real thermal throttling event from the Thermal HAL could be
-// inadvertently received here.
 TEST_P(ThermalHidlTest, NotifyThrottlingTest) {
     sp<ThermalCallback> thermalCallback = new (std::nothrow) ThermalCallback();
     auto ret = thermalCallback->notifyThrottling(kThrottleTemp);
diff --git a/tv/Android.mk b/tv/Android.mk
new file mode 100644
index 0000000..d78614a
--- /dev/null
+++ b/tv/Android.mk
@@ -0,0 +1,2 @@
+$(eval $(call declare-1p-copy-files,hardware/interfaces/tv,tuner_vts_config_1_0.xml))
+$(eval $(call declare-1p-copy-files,hardware/interfaces/tv,tuner_vts_config_1_1.xml))
diff --git a/tv/cec/1.0/default/Android.bp b/tv/cec/1.0/default/Android.bp
index fc4298d..e4c226d 100644
--- a/tv/cec/1.0/default/Android.bp
+++ b/tv/cec/1.0/default/Android.bp
@@ -12,12 +12,17 @@
     defaults: ["hidl_defaults"],
     vendor: true,
     relative_install_path: "hw",
-    srcs: ["HdmiCec.cpp"],
+    srcs: [
+        "HdmiCec.cpp",
+        "HdmiCecDefault.cpp",
+        "HdmiCecPort.cpp",
+    ],
 
     shared_libs: [
         "libhidlbase",
         "liblog",
         "libbase",
+        "libcutils",
         "libutils",
         "libhardware",
         "android.hardware.tv.cec@1.0",
diff --git a/tv/cec/1.0/default/HdmiCec.cpp b/tv/cec/1.0/default/HdmiCec.cpp
index 171bdfe..74de785 100644
--- a/tv/cec/1.0/default/HdmiCec.cpp
+++ b/tv/cec/1.0/default/HdmiCec.cpp
@@ -20,6 +20,7 @@
 #include <hardware/hardware.h>
 #include <hardware/hdmi_cec.h>
 #include "HdmiCec.h"
+#include "HdmiCecDefault.h"
 
 namespace android {
 namespace hardware {
@@ -390,6 +391,15 @@
     return mDevice->is_connected(mDevice, portId) > 0;
 }
 
+IHdmiCec* getHdmiCecDefault() {
+    HdmiCecDefault* hdmiCecDefault = new HdmiCecDefault();
+    Result result = hdmiCecDefault->init();
+    if (result == Result::SUCCESS) {
+        return hdmiCecDefault;
+    }
+    LOG(ERROR) << "Failed to load default HAL.";
+    return nullptr;
+}
 
 IHdmiCec* HIDL_FETCH_IHdmiCec(const char* hal) {
     hdmi_cec_device_t* hdmi_cec_device;
@@ -410,7 +420,7 @@
         return new HdmiCec(hdmi_cec_device);
     } else {
         LOG(ERROR) << "Passthrough failed to load legacy HAL.";
-        return nullptr;
+        return getHdmiCecDefault();
     }
 }
 
diff --git a/tv/cec/1.0/default/HdmiCecDefault.cpp b/tv/cec/1.0/default/HdmiCecDefault.cpp
new file mode 100644
index 0000000..26ccb7d
--- /dev/null
+++ b/tv/cec/1.0/default/HdmiCecDefault.cpp
@@ -0,0 +1,519 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.tv.cec@1.0-impl"
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+
+#include <cutils/properties.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/ioctl.h>
+#include <poll.h>
+
+#include "HdmiCecDefault.h"
+
+#define PROPERTY_DEVICE_TYPE "ro.hdmi.device_type"
+#define MIN_PORT_ID 0
+#define MAX_PORT_ID 15
+#define INVALID_PHYSICAL_ADDRESS 0xFFFF
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace cec {
+namespace V1_0 {
+namespace implementation {
+
+using android::base::GetUintProperty;
+using std::stoi;
+using std::string;
+
+HdmiCecDefault::HdmiCecDefault() {
+    mCecEnabled = false;
+    mWakeupEnabled = false;
+    mCecControlEnabled = false;
+    mCallback = nullptr;
+}
+
+HdmiCecDefault::~HdmiCecDefault() {
+    release();
+}
+
+// Methods from ::android::hardware::tv::cec::V1_0::IHdmiCec follow.
+Return<Result> HdmiCecDefault::addLogicalAddress(CecLogicalAddress addr) {
+    if (addr < CecLogicalAddress::TV || addr >= CecLogicalAddress::BROADCAST) {
+        LOG(ERROR) << "Add logical address failed, Invalid address";
+        return Result::FAILURE_INVALID_ARGS;
+    }
+
+    cec_log_addrs cecLogAddrs;
+    int ret = ioctl(mHdmiCecPorts[MIN_PORT_ID]->mCecFd, CEC_ADAP_G_LOG_ADDRS, &cecLogAddrs);
+    if (ret) {
+        LOG(ERROR) << "Add logical address failed, Error = " << strerror(errno);
+        return Result::FAILURE_BUSY;
+    }
+
+    cecLogAddrs.cec_version = getCecVersion();
+    cecLogAddrs.vendor_id = getVendorId();
+
+    unsigned int logAddrType = CEC_LOG_ADDR_TYPE_UNREGISTERED;
+    unsigned int allDevTypes = 0;
+    unsigned int primDevType = 0xff;
+    switch (addr) {
+        case CecLogicalAddress::TV:
+            primDevType = CEC_OP_PRIM_DEVTYPE_TV;
+            logAddrType = CEC_LOG_ADDR_TYPE_TV;
+            allDevTypes = CEC_OP_ALL_DEVTYPE_TV;
+            break;
+        case CecLogicalAddress::RECORDER_1:
+        case CecLogicalAddress::RECORDER_2:
+        case CecLogicalAddress::RECORDER_3:
+            primDevType = CEC_OP_PRIM_DEVTYPE_RECORD;
+            logAddrType = CEC_LOG_ADDR_TYPE_RECORD;
+            allDevTypes = CEC_OP_ALL_DEVTYPE_RECORD;
+            break;
+        case CecLogicalAddress::TUNER_1:
+        case CecLogicalAddress::TUNER_2:
+        case CecLogicalAddress::TUNER_3:
+        case CecLogicalAddress::TUNER_4:
+            primDevType = CEC_OP_PRIM_DEVTYPE_TUNER;
+            logAddrType = CEC_LOG_ADDR_TYPE_TUNER;
+            allDevTypes = CEC_OP_ALL_DEVTYPE_TUNER;
+            break;
+        case CecLogicalAddress::PLAYBACK_1:
+        case CecLogicalAddress::PLAYBACK_2:
+        case CecLogicalAddress::PLAYBACK_3:
+            primDevType = CEC_OP_PRIM_DEVTYPE_PLAYBACK;
+            logAddrType = CEC_LOG_ADDR_TYPE_PLAYBACK;
+            allDevTypes = CEC_OP_ALL_DEVTYPE_PLAYBACK;
+            cecLogAddrs.flags |= CEC_LOG_ADDRS_FL_ALLOW_RC_PASSTHRU;
+            break;
+        case CecLogicalAddress::AUDIO_SYSTEM:
+            primDevType = CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM;
+            logAddrType = CEC_LOG_ADDR_TYPE_AUDIOSYSTEM;
+            allDevTypes = CEC_OP_ALL_DEVTYPE_AUDIOSYSTEM;
+            break;
+        case CecLogicalAddress::FREE_USE:
+            primDevType = CEC_OP_PRIM_DEVTYPE_PROCESSOR;
+            logAddrType = CEC_LOG_ADDR_TYPE_SPECIFIC;
+            allDevTypes = CEC_OP_ALL_DEVTYPE_SWITCH;
+            break;
+        case CecLogicalAddress::UNREGISTERED:
+            cecLogAddrs.flags |= CEC_LOG_ADDRS_FL_ALLOW_UNREG_FALLBACK;
+            break;
+    }
+
+    int logAddrIndex = cecLogAddrs.num_log_addrs;
+
+    cecLogAddrs.num_log_addrs += 1;
+    cecLogAddrs.log_addr[logAddrIndex] = static_cast<cec_logical_address_t>(addr);
+    cecLogAddrs.log_addr_type[logAddrIndex] = logAddrType;
+    cecLogAddrs.primary_device_type[logAddrIndex] = primDevType;
+    cecLogAddrs.all_device_types[logAddrIndex] = allDevTypes;
+    cecLogAddrs.features[logAddrIndex][0] = 0;
+    cecLogAddrs.features[logAddrIndex][1] = 0;
+
+    // Return failure only if add logical address fails for all the ports
+    Return<Result> result = Result::FAILURE_BUSY;
+    for (int i = 0; i < mHdmiCecPorts.size(); i++) {
+        ret = ioctl(mHdmiCecPorts[i]->mCecFd, CEC_ADAP_S_LOG_ADDRS, &cecLogAddrs);
+        if (ret) {
+            LOG(ERROR) << "Add logical address failed for port " << mHdmiCecPorts[i]->mPortId
+                       << ", Error = " << strerror(errno);
+        } else {
+            result = Result::SUCCESS;
+        }
+    }
+    return result;
+}
+
+Return<void> HdmiCecDefault::clearLogicalAddress() {
+    cec_log_addrs cecLogAddrs;
+    memset(&cecLogAddrs, 0, sizeof(cecLogAddrs));
+    for (int i = 0; i < mHdmiCecPorts.size(); i++) {
+        int ret = ioctl(mHdmiCecPorts[i]->mCecFd, CEC_ADAP_S_LOG_ADDRS, &cecLogAddrs);
+        if (ret) {
+            LOG(ERROR) << "Clear logical Address failed for port " << mHdmiCecPorts[i]->mPortId
+                       << ", Error = " << strerror(errno);
+        }
+    }
+    return Void();
+}
+
+Return<void> HdmiCecDefault::getPhysicalAddress(getPhysicalAddress_cb callback) {
+    uint16_t addr;
+    int ret = ioctl(mHdmiCecPorts[MIN_PORT_ID]->mCecFd, CEC_ADAP_G_PHYS_ADDR, &addr);
+    if (ret) {
+        LOG(ERROR) << "Get physical address failed, Error = " << strerror(errno);
+        callback(Result::FAILURE_INVALID_STATE, addr);
+        return Void();
+    }
+    callback(Result::SUCCESS, addr);
+    return Void();
+}
+
+Return<SendMessageResult> HdmiCecDefault::sendMessage(const CecMessage& message) {
+    if (!mCecEnabled) {
+        return SendMessageResult::FAIL;
+    }
+
+    cec_msg cecMsg;
+    memset(&cecMsg, 0, sizeof(cec_msg));
+
+    int initiator = static_cast<cec_logical_address_t>(message.initiator);
+    int destination = static_cast<cec_logical_address_t>(message.destination);
+
+    cecMsg.msg[0] = (initiator << 4) | destination;
+    for (size_t i = 0; i < message.body.size(); ++i) {
+        cecMsg.msg[i + 1] = message.body[i];
+    }
+    cecMsg.len = message.body.size() + 1;
+
+    // Return failure only if send message fails for all the ports
+    Return<SendMessageResult> result = SendMessageResult::FAIL;
+    for (int i = 0; i < mHdmiCecPorts.size(); i++) {
+        int ret = ioctl(mHdmiCecPorts[i]->mCecFd, CEC_TRANSMIT, &cecMsg);
+
+        if (ret) {
+            LOG(ERROR) << "Send message failed, Error = " << strerror(errno);
+            continue;
+        }
+
+        if (cecMsg.tx_status != CEC_TX_STATUS_OK) {
+            LOG(ERROR) << "Send message tx_status = " << cecMsg.tx_status;
+        }
+
+        if (result != SendMessageResult::SUCCESS) {
+            result = getSendMessageResult(cecMsg.tx_status);
+        }
+    }
+    return result;
+}
+
+Return<void> HdmiCecDefault::setCallback(const sp<IHdmiCecCallback>& callback) {
+    if (mCallback != nullptr) {
+        mCallback->unlinkToDeath(this);
+        mCallback = nullptr;
+    }
+
+    if (callback != nullptr) {
+        mCallback = callback;
+        mCallback->linkToDeath(this, 0 /*cookie*/);
+    }
+    return Void();
+}
+
+Return<int32_t> HdmiCecDefault::getCecVersion() {
+    return property_get_int32("ro.hdmi.cec_version", CEC_OP_CEC_VERSION_1_4);
+}
+
+Return<uint32_t> HdmiCecDefault::getVendorId() {
+    return property_get_int32("ro.hdmi.vendor_id", 0x000c03 /* HDMI LLC vendor ID */);
+}
+
+Return<void> HdmiCecDefault::getPortInfo(getPortInfo_cb callback) {
+    hidl_vec<HdmiPortInfo> portInfos(mHdmiCecPorts.size());
+    for (int i = 0; i < mHdmiCecPorts.size(); i++) {
+        uint16_t addr = INVALID_PHYSICAL_ADDRESS;
+        int ret = ioctl(mHdmiCecPorts[i]->mCecFd, CEC_ADAP_G_PHYS_ADDR, &addr);
+        if (ret) {
+            LOG(ERROR) << "Get port info failed for port : " << mHdmiCecPorts[i]->mPortId
+                       << ", Error = " << strerror(errno);
+        }
+        HdmiPortType type = HdmiPortType::INPUT;
+        uint32_t deviceType = GetUintProperty<uint32_t>(PROPERTY_DEVICE_TYPE, CEC_DEVICE_PLAYBACK);
+        if (deviceType != CEC_DEVICE_TV && i == MIN_PORT_ID) {
+            type = HdmiPortType::OUTPUT;
+        }
+        portInfos[i] = {.type = type,
+                        .portId = mHdmiCecPorts[i]->mPortId,
+                        .cecSupported = true,
+                        .arcSupported = false,
+                        .physicalAddress = addr};
+    }
+    callback(portInfos);
+    return Void();
+}
+
+Return<void> HdmiCecDefault::setOption(OptionKey key, bool value) {
+    switch (key) {
+        case OptionKey::ENABLE_CEC:
+            LOG(DEBUG) << "setOption: Enable CEC: " << value;
+            mCecEnabled = value;
+            break;
+        case OptionKey::WAKEUP:
+            LOG(DEBUG) << "setOption: WAKEUP: " << value;
+            mWakeupEnabled = value;
+            break;
+        case OptionKey::SYSTEM_CEC_CONTROL:
+            LOG(DEBUG) << "setOption: SYSTEM_CEC_CONTROL: " << value;
+            mCecControlEnabled = value;
+            break;
+    }
+    return Void();
+}
+
+Return<void> HdmiCecDefault::setLanguage(const hidl_string& /*language*/) {
+    return Void();
+}
+
+Return<void> HdmiCecDefault::enableAudioReturnChannel(int32_t /*portId*/, bool /*enable*/) {
+    return Void();
+}
+
+Return<bool> HdmiCecDefault::isConnected(int32_t portId) {
+    uint16_t addr;
+    int ret = ioctl(mHdmiCecPorts[portId]->mCecFd, CEC_ADAP_G_PHYS_ADDR, &addr);
+    if (ret) {
+        LOG(ERROR) << "Is connected failed, Error = " << strerror(errno);
+        return false;
+    }
+    if (addr == CEC_PHYS_ADDR_INVALID) {
+        return false;
+    }
+    return true;
+}
+
+int getPortId(string cecFilename) {
+    int portId = stoi(cecFilename.substr(3));
+    if (portId >= MIN_PORT_ID && portId <= MAX_PORT_ID) {
+        return portId;
+    } else {
+        return -1;
+    }
+}
+
+// Initialise the cec file descriptors
+Return<Result> HdmiCecDefault::init() {
+    const char* parentPath = "/dev/";
+    DIR* dir = opendir(parentPath);
+    const char* cecFilename = "cec";
+
+    while (struct dirent* dirEntry = readdir(dir)) {
+        string filename = dirEntry->d_name;
+        if (filename.compare(0, 3, cecFilename, 0, 3) == 0) {
+            int portId = getPortId(filename);
+            if (portId == -1) {
+                continue;
+            }
+            shared_ptr<HdmiCecPort> hdmiCecPort(new HdmiCecPort(portId));
+            string filepath = parentPath + filename;
+            Result result = hdmiCecPort->init(filepath.c_str());
+            if (result != Result::SUCCESS) {
+                continue;
+            }
+            thread eventThread(&HdmiCecDefault::event_thread, this, hdmiCecPort.get());
+            mEventThreads.push_back(std::move(eventThread));
+            mHdmiCecPorts.push_back(std::move(hdmiCecPort));
+        }
+    }
+
+    if (mHdmiCecPorts.empty()) {
+        return Result::FAILURE_NOT_SUPPORTED;
+    }
+
+    mCecEnabled = true;
+    mWakeupEnabled = true;
+    mCecControlEnabled = true;
+    return Result::SUCCESS;
+}
+
+Return<void> HdmiCecDefault::release() {
+    mCecEnabled = false;
+    mWakeupEnabled = false;
+    mCecControlEnabled = false;
+    for (thread& eventThread : mEventThreads) {
+        if (eventThread.joinable()) {
+            eventThread.join();
+        }
+    }
+    setCallback(nullptr);
+    mHdmiCecPorts.clear();
+    mEventThreads.clear();
+    return Void();
+}
+
+void HdmiCecDefault::event_thread(HdmiCecPort* hdmiCecPort) {
+    struct pollfd ufds[3] = {
+            {hdmiCecPort->mCecFd, POLLIN, 0},
+            {hdmiCecPort->mCecFd, POLLERR, 0},
+            {hdmiCecPort->mExitFd, POLLIN, 0},
+    };
+
+    while (1) {
+        ufds[0].revents = 0;
+        ufds[1].revents = 0;
+        ufds[2].revents = 0;
+
+        int ret = poll(ufds, /* size(ufds) = */ 3, /* timeout = */ -1);
+
+        if (ret <= 0) {
+            continue;
+        }
+
+        if (ufds[2].revents == POLLIN) { /* Exit */
+            break;
+        }
+
+        if (ufds[1].revents == POLLERR) { /* CEC Event */
+            cec_event ev;
+            ret = ioctl(hdmiCecPort->mCecFd, CEC_DQEVENT, &ev);
+
+            if (ret) {
+                LOG(ERROR) << "CEC_DQEVENT failed, Error = " << strerror(errno);
+                continue;
+            }
+
+            if (!mCecEnabled) {
+                continue;
+            }
+
+            if (ev.event == CEC_EVENT_STATE_CHANGE) {
+                if (mCallback != nullptr) {
+                    HotplugEvent hotplugEvent{
+                            .connected = (ev.state_change.phys_addr != CEC_PHYS_ADDR_INVALID),
+                            .portId = hdmiCecPort->mPortId};
+                    mCallback->onHotplugEvent(hotplugEvent);
+                } else {
+                    LOG(ERROR) << "No event callback for hotplug";
+                }
+            }
+        }
+
+        if (ufds[0].revents == POLLIN) { /* CEC Driver */
+            cec_msg msg = {};
+            ret = ioctl(hdmiCecPort->mCecFd, CEC_RECEIVE, &msg);
+
+            if (ret) {
+                LOG(ERROR) << "CEC_RECEIVE failed, Error = " << strerror(errno);
+                continue;
+            }
+
+            if (msg.rx_status != CEC_RX_STATUS_OK) {
+                LOG(ERROR) << "msg rx_status = " << msg.rx_status;
+                continue;
+            }
+
+            if (!mCecEnabled) {
+                continue;
+            }
+
+            if (!mWakeupEnabled && isWakeupMessage(msg)) {
+                LOG(DEBUG) << "Filter wakeup message";
+                continue;
+            }
+
+            if (!mCecControlEnabled && !isTransferableInSleep(msg)) {
+                LOG(DEBUG) << "Filter message in standby mode";
+                continue;
+            }
+
+            if (mCallback != nullptr) {
+                size_t length = std::min(msg.len - 1, (uint32_t)MaxLength::MESSAGE_BODY);
+                CecMessage cecMessage{
+                        .initiator = static_cast<CecLogicalAddress>(msg.msg[0] >> 4),
+                        .destination = static_cast<CecLogicalAddress>(msg.msg[0] & 0xf),
+                };
+                cecMessage.body.resize(length);
+                for (size_t i = 0; i < length; ++i) {
+                    cecMessage.body[i] = static_cast<uint8_t>(msg.msg[i + 1]);
+                }
+                mCallback->onCecMessage(cecMessage);
+            } else {
+                LOG(ERROR) << "no event callback for message";
+            }
+        }
+    }
+}
+
+int HdmiCecDefault::getOpcode(cec_msg message) {
+    return static_cast<uint8_t>(message.msg[1]);
+}
+
+bool HdmiCecDefault::isWakeupMessage(cec_msg message) {
+    int opcode = getOpcode(message);
+    switch (opcode) {
+        case CEC_MESSAGE_TEXT_VIEW_ON:
+        case CEC_MESSAGE_IMAGE_VIEW_ON:
+            return true;
+        default:
+            return false;
+    }
+}
+
+bool HdmiCecDefault::isTransferableInSleep(cec_msg message) {
+    int opcode = getOpcode(message);
+    switch (opcode) {
+        case CEC_MESSAGE_ABORT:
+        case CEC_MESSAGE_DEVICE_VENDOR_ID:
+        case CEC_MESSAGE_GET_CEC_VERSION:
+        case CEC_MESSAGE_GET_MENU_LANGUAGE:
+        case CEC_MESSAGE_GIVE_DEVICE_POWER_STATUS:
+        case CEC_MESSAGE_GIVE_DEVICE_VENDOR_ID:
+        case CEC_MESSAGE_GIVE_OSD_NAME:
+        case CEC_MESSAGE_GIVE_PHYSICAL_ADDRESS:
+        case CEC_MESSAGE_REPORT_PHYSICAL_ADDRESS:
+        case CEC_MESSAGE_REPORT_POWER_STATUS:
+        case CEC_MESSAGE_SET_OSD_NAME:
+        case CEC_MESSAGE_DECK_CONTROL:
+        case CEC_MESSAGE_PLAY:
+        case CEC_MESSAGE_IMAGE_VIEW_ON:
+        case CEC_MESSAGE_TEXT_VIEW_ON:
+        case CEC_MESSAGE_SYSTEM_AUDIO_MODE_REQUEST:
+            return true;
+        case CEC_MESSAGE_USER_CONTROL_PRESSED:
+            return isPowerUICommand(message);
+        default:
+            return false;
+    }
+}
+
+int HdmiCecDefault::getFirstParam(cec_msg message) {
+    return static_cast<uint8_t>(message.msg[2]);
+}
+
+bool HdmiCecDefault::isPowerUICommand(cec_msg message) {
+    int uiCommand = getFirstParam(message);
+    switch (uiCommand) {
+        case CEC_OP_UI_CMD_POWER:
+        case CEC_OP_UI_CMD_DEVICE_ROOT_MENU:
+        case CEC_OP_UI_CMD_POWER_ON_FUNCTION:
+            return true;
+        default:
+            return false;
+    }
+}
+
+Return<SendMessageResult> HdmiCecDefault::getSendMessageResult(int tx_status) {
+    switch (tx_status) {
+        case CEC_TX_STATUS_OK:
+            return SendMessageResult::SUCCESS;
+        case CEC_TX_STATUS_ARB_LOST:
+            return SendMessageResult::BUSY;
+        case CEC_TX_STATUS_NACK:
+            return SendMessageResult::NACK;
+        default:
+            return SendMessageResult::FAIL;
+    }
+}
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace cec
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
diff --git a/tv/cec/1.0/default/HdmiCecDefault.h b/tv/cec/1.0/default/HdmiCecDefault.h
new file mode 100644
index 0000000..6574429
--- /dev/null
+++ b/tv/cec/1.0/default/HdmiCecDefault.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <hardware/hdmi_cec.h>
+#include <linux/cec.h>
+#include <thread>
+#include <vector>
+#include "HdmiCecPort.h"
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace cec {
+namespace V1_0 {
+namespace implementation {
+
+using std::shared_ptr;
+using std::thread;
+using std::vector;
+
+class HdmiCecDefault : public IHdmiCec, public hidl_death_recipient {
+  public:
+    HdmiCecDefault();
+    ~HdmiCecDefault();
+    // Methods from ::android::hardware::tv::cec::V1_0::IHdmiCec follow.
+    Return<Result> addLogicalAddress(CecLogicalAddress addr) override;
+    Return<void> clearLogicalAddress() override;
+    Return<void> getPhysicalAddress(getPhysicalAddress_cb _hidl_cb) override;
+    Return<SendMessageResult> sendMessage(const CecMessage& message) override;
+    Return<void> setCallback(const sp<IHdmiCecCallback>& callback) override;
+    Return<int32_t> getCecVersion() override;
+    Return<uint32_t> getVendorId() override;
+    Return<void> getPortInfo(getPortInfo_cb _hidl_cb) override;
+    Return<void> setOption(OptionKey key, bool value) override;
+    Return<void> setLanguage(const hidl_string& language) override;
+    Return<void> enableAudioReturnChannel(int32_t portId, bool enable) override;
+    Return<bool> isConnected(int32_t portId) override;
+
+    virtual void serviceDied(uint64_t, const wp<::android::hidl::base::V1_0::IBase>&) {
+        setCallback(nullptr);
+    }
+
+    Return<Result> init();
+    Return<void> release();
+
+  private:
+    void event_thread(HdmiCecPort* hdmiCecPort);
+    static int getOpcode(cec_msg message);
+    static int getFirstParam(cec_msg message);
+    static bool isWakeupMessage(cec_msg message);
+    static bool isTransferableInSleep(cec_msg message);
+    static bool isPowerUICommand(cec_msg message);
+    static Return<SendMessageResult> getSendMessageResult(int tx_status);
+
+    vector<thread> mEventThreads;
+    vector<shared_ptr<HdmiCecPort>> mHdmiCecPorts;
+
+    // When set to false, all the CEC commands are discarded. True by default after initialization.
+    bool mCecEnabled;
+    /*
+     * When set to false, HAL does not wake up the system upon receiving <Image View On> or
+     * <Text View On>. True by default after initialization.
+     */
+    bool mWakeupEnabled;
+    /*
+     * Updated when system goes into or comes out of standby mode.
+     * When set to true, Android system is handling CEC commands.
+     * When set to false, microprocessor is handling CEC commands.
+     * True by default after initialization.
+     */
+    bool mCecControlEnabled;
+    sp<IHdmiCecCallback> mCallback;
+};
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace cec
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
diff --git a/tv/cec/1.0/default/HdmiCecPort.cpp b/tv/cec/1.0/default/HdmiCecPort.cpp
new file mode 100755
index 0000000..73dda12
--- /dev/null
+++ b/tv/cec/1.0/default/HdmiCecPort.cpp
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "android.hardware.tv.cec@1.0-impl"
+
+#include <android-base/logging.h>
+#include <errno.h>
+#include <linux/cec.h>
+#include <linux/ioctl.h>
+#include <sys/eventfd.h>
+#include <algorithm>
+
+#include "HdmiCecPort.h"
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace cec {
+namespace V1_0 {
+namespace implementation {
+
+HdmiCecPort::HdmiCecPort(unsigned int portId) {
+    mPortId = portId;
+    mCecFd = -1;
+    mExitFd = -1;
+}
+
+HdmiCecPort::~HdmiCecPort() {
+    release();
+}
+
+// Initialise the cec file descriptor
+Return<Result> HdmiCecPort::init(const char* path) {
+    mCecFd = open(path, O_RDWR);
+    if (mCecFd < 0) {
+        LOG(ERROR) << "Failed to open " << path << ", Error = " << strerror(errno);
+        return Result::FAILURE_NOT_SUPPORTED;
+    }
+    mExitFd = eventfd(0, EFD_NONBLOCK);
+    if (mExitFd < 0) {
+        LOG(ERROR) << "Failed to open eventfd, Error = " << strerror(errno);
+        release();
+        return Result::FAILURE_NOT_SUPPORTED;
+    }
+
+    // Ensure the CEC device supports required capabilities
+    struct cec_caps caps = {};
+    int ret = ioctl(mCecFd, CEC_ADAP_G_CAPS, &caps);
+    if (ret) {
+        LOG(ERROR) << "Unable to query cec adapter capabilities, Error = " << strerror(errno);
+        release();
+        return Result::FAILURE_NOT_SUPPORTED;
+    }
+
+    if (!(caps.capabilities & (CEC_CAP_LOG_ADDRS | CEC_CAP_TRANSMIT | CEC_CAP_PASSTHROUGH))) {
+        LOG(ERROR) << "Wrong cec adapter capabilities " << caps.capabilities;
+        release();
+        return Result::FAILURE_NOT_SUPPORTED;
+    }
+
+    uint32_t mode = CEC_MODE_INITIATOR | CEC_MODE_EXCL_FOLLOWER_PASSTHRU;
+    ret = ioctl(mCecFd, CEC_S_MODE, &mode);
+    if (ret) {
+        LOG(ERROR) << "Unable to set initiator mode, Error = " << strerror(errno);
+        release();
+        return Result::FAILURE_NOT_SUPPORTED;
+    }
+    return Result::SUCCESS;
+}
+
+Return<void> HdmiCecPort::release() {
+    if (mExitFd > 0) {
+        uint64_t tmp = 1;
+        write(mExitFd, &tmp, sizeof(tmp));
+    }
+    if (mExitFd > 0) {
+        close(mExitFd);
+    }
+    if (mCecFd > 0) {
+        close(mCecFd);
+    }
+    return Void();
+}
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace cec
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
diff --git a/tv/cec/1.0/default/HdmiCecPort.h b/tv/cec/1.0/default/HdmiCecPort.h
new file mode 100755
index 0000000..2a2fdef
--- /dev/null
+++ b/tv/cec/1.0/default/HdmiCecPort.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <android/hardware/tv/cec/1.0/IHdmiCec.h>
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace cec {
+namespace V1_0 {
+namespace implementation {
+
+class HdmiCecPort {
+  public:
+    HdmiCecPort(unsigned int portId);
+    ~HdmiCecPort();
+    Return<Result> init(const char* path);
+    Return<void> release();
+
+    unsigned int mPortId;
+    int mCecFd;
+    int mExitFd;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace cec
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
diff --git a/tv/cec/1.0/default/OWNERS b/tv/cec/1.0/default/OWNERS
new file mode 100644
index 0000000..c1d3f1d
--- /dev/null
+++ b/tv/cec/1.0/default/OWNERS
@@ -0,0 +1 @@
+include platform/frameworks/base:/core/java/android/hardware/hdmi/OWNERS
diff --git a/tv/tuner/1.0/default/android.hardware.tv.tuner@1.0-service-lazy.rc b/tv/tuner/1.0/default/android.hardware.tv.tuner@1.0-service-lazy.rc
index ad72fae..ed62cee 100644
--- a/tv/tuner/1.0/default/android.hardware.tv.tuner@1.0-service-lazy.rc
+++ b/tv/tuner/1.0/default/android.hardware.tv.tuner@1.0-service-lazy.rc
@@ -6,4 +6,4 @@
     user media
     group mediadrm drmrpc
     ioprio rt 4
-    writepid /dev/cpuset/foreground/tasks
\ No newline at end of file
+    task_profiles ProcessCapacityHigh
diff --git a/tv/tuner/1.0/default/android.hardware.tv.tuner@1.0-service.rc b/tv/tuner/1.0/default/android.hardware.tv.tuner@1.0-service.rc
index 6d59ed7..5d5b943 100644
--- a/tv/tuner/1.0/default/android.hardware.tv.tuner@1.0-service.rc
+++ b/tv/tuner/1.0/default/android.hardware.tv.tuner@1.0-service.rc
@@ -3,4 +3,4 @@
     user media
     group mediadrm drmrpc
     ioprio rt 4
-    writepid /dev/cpuset/foreground/tasks
\ No newline at end of file
+    task_profiles ProcessCapacityHigh
diff --git a/tv/tuner/1.0/vts/functional/FrontendTests.cpp b/tv/tuner/1.0/vts/functional/FrontendTests.cpp
index b35d112..6cf7d1d 100644
--- a/tv/tuner/1.0/vts/functional/FrontendTests.cpp
+++ b/tv/tuner/1.0/vts/functional/FrontendTests.cpp
@@ -128,7 +128,8 @@
     }
 
     EXPECT_TRUE(scanMsgLockedReceived) << "Scan message LOCKED not received before END";
-    EXPECT_TRUE(targetFrequencyReceived) << "frequency not received before LOCKED on blindScan";
+    if (type == FrontendScanType::SCAN_BLIND)
+        EXPECT_TRUE(targetFrequencyReceived) << "frequency not received before LOCKED on blindScan";
     mScanMessageReceived = false;
     mScanMsgProcessed = true;
 }
diff --git a/tv/tuner/1.1/default/android.hardware.tv.tuner@1.1-service-lazy.rc b/tv/tuner/1.1/default/android.hardware.tv.tuner@1.1-service-lazy.rc
index abff430..3fe6b52 100644
--- a/tv/tuner/1.1/default/android.hardware.tv.tuner@1.1-service-lazy.rc
+++ b/tv/tuner/1.1/default/android.hardware.tv.tuner@1.1-service-lazy.rc
@@ -7,4 +7,4 @@
     user media
     group mediadrm drmrpc
     ioprio rt 4
-    writepid /dev/cpuset/foreground/tasks
\ No newline at end of file
+    task_profiles ProcessCapacityHigh
diff --git a/tv/tuner/1.1/default/android.hardware.tv.tuner@1.1-service.rc b/tv/tuner/1.1/default/android.hardware.tv.tuner@1.1-service.rc
index 3718a93..bc62c7d 100644
--- a/tv/tuner/1.1/default/android.hardware.tv.tuner@1.1-service.rc
+++ b/tv/tuner/1.1/default/android.hardware.tv.tuner@1.1-service.rc
@@ -3,4 +3,4 @@
     user media
     group mediadrm drmrpc
     ioprio rt 4
-    writepid /dev/cpuset/foreground/tasks
\ No newline at end of file
+    task_profiles ProcessCapacityHigh
diff --git a/tv/tuner/1.1/vts/functional/FrontendTests.cpp b/tv/tuner/1.1/vts/functional/FrontendTests.cpp
index 9c575ff..7afffb8 100644
--- a/tv/tuner/1.1/vts/functional/FrontendTests.cpp
+++ b/tv/tuner/1.1/vts/functional/FrontendTests.cpp
@@ -180,7 +180,8 @@
     }
 
     EXPECT_TRUE(scanMsgLockedReceived) << "Scan message LOCKED not received before END";
-    EXPECT_TRUE(targetFrequencyReceived) << "frequency not received before LOCKED on blindScan";
+    if (type == FrontendScanType::SCAN_BLIND)
+        EXPECT_TRUE(targetFrequencyReceived) << "frequency not received before LOCKED on blindScan";
     mScanMessageReceived = false;
     mScanMsgProcessed = true;
 }
diff --git a/update-base-files.sh b/update-base-files.sh
index d01847d..bf7f6e4 100755
--- a/update-base-files.sh
+++ b/update-base-files.sh
@@ -45,8 +45,11 @@
          -o $ANDROID_BUILD_TOP/system/media/audio/include/system/audio_common-base.h \
          android.hardware.audio.common@7.0
 hidl-gen $options \
-         -o $ANDROID_BUILD_TOP/system/media/audio/include/system/audio-base.h \
+         -o $ANDROID_BUILD_TOP/system/media/audio/include/system/audio-base-v7.0.h \
          android.hardware.audio@7.0
 hidl-gen $options \
+         -o $ANDROID_BUILD_TOP/system/media/audio/include/system/audio-base-v7.1.h \
+         android.hardware.audio@7.1
+hidl-gen $options \
          -o $ANDROID_BUILD_TOP/system/media/audio/include/system/audio_effect-base.h \
          android.hardware.audio.effect@7.0
diff --git a/usb/1.0/default/Android.bp b/usb/1.0/default/Android.bp
index 5f56fe0..4bed2c7 100644
--- a/usb/1.0/default/Android.bp
+++ b/usb/1.0/default/Android.bp
@@ -21,11 +21,21 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
+filegroup {
+    name: "android.hardware.usb@1.0-service.xml",
+    srcs: ["android.hardware.usb@1.0-service.xml"],
+}
+
+filegroup {
+    name: "android.hardware.usb@1.0-service.rc",
+    srcs: ["android.hardware.usb@1.0-service.rc"],
+}
+
 cc_binary {
     name: "android.hardware.usb@1.0-service",
     defaults: ["hidl_defaults"],
-    init_rc: ["android.hardware.usb@1.0-service.rc"],
-    vintf_fragments: ["android.hardware.usb@1.0-service.xml"],
+    init_rc: [":android.hardware.usb@1.0-service.rc"],
+    vintf_fragments: [":android.hardware.usb@1.0-service.xml"],
     relative_install_path: "hw",
     vendor: true,
     srcs: [
diff --git a/usb/1.0/default/apex/Android.bp b/usb/1.0/default/apex/Android.bp
new file mode 100644
index 0000000..ee50fdf
--- /dev/null
+++ b/usb/1.0/default/apex/Android.bp
@@ -0,0 +1,59 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+apex_key {
+    name: "com.android.hardware.usb.key",
+    public_key: "com.android.hardware.usb.avbpubkey",
+    private_key: "com.android.hardware.usb.pem",
+}
+
+android_app_certificate {
+    name: "com.android.hardware.usb.certificate",
+    certificate: "com.android.hardware.usb",
+}
+
+genrule {
+    name: "com.android.hardware.usb.rc-gen",
+    srcs: [":android.hardware.usb@1.0-service.rc"],
+    out: ["com.android.hardware.usb.rc"],
+    cmd: "sed -E 's/\\/vendor/\\/apex\\/com.android.hardware.usb/' $(in) > $(out)",
+}
+
+prebuilt_etc {
+    name: "com.android.hardware.usb.rc",
+    src: ":com.android.hardware.usb.rc-gen",
+    installable: false,
+}
+
+apex {
+    name: "com.android.hardware.usb",
+    manifest: "manifest.json",
+    file_contexts: "file_contexts",
+    key: "com.android.hardware.usb.key",
+    certificate: ":com.android.hardware.usb.certificate",
+    updatable: false,
+    soc_specific: true,
+    use_vndk_as_stable: true,
+    binaries: ["android.hardware.usb@1.0-service"],
+    prebuilts: [
+        "com.android.hardware.usb.rc",
+        "android.hardware.usb.accessory.prebuilt.xml",
+        "android.hardware.usb.host.prebuilt.xml",
+    ],
+    vintf_fragments: [":android.hardware.usb@1.0-service.xml"],
+}
diff --git a/usb/1.0/default/apex/com.android.hardware.usb.avbpubkey b/usb/1.0/default/apex/com.android.hardware.usb.avbpubkey
new file mode 100644
index 0000000..0302d63
--- /dev/null
+++ b/usb/1.0/default/apex/com.android.hardware.usb.avbpubkey
Binary files differ
diff --git a/usb/1.0/default/apex/com.android.hardware.usb.pem b/usb/1.0/default/apex/com.android.hardware.usb.pem
new file mode 100644
index 0000000..e1e57da
--- /dev/null
+++ b/usb/1.0/default/apex/com.android.hardware.usb.pem
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIJKQIBAAKCAgEAwdimmHgIZHrep3H3YfVaNYEAGg45LUEPIiwHV6aIC9V7zjBS
+SftD30Z21jGyk7hmtas6WMI2vRBDNGrZWDgPeiEQoxXQinuU4Ug5S5X2F8LpWs0y
+ZeNFwQkqZwqGdQlkmy8upfb6T7rDxqRv+C0AtGP1r4r36+Xh5ld5stVaMK0UNhZt
+VW0nQAxyeJL3tm0zfiEA9Zu7FF2IyHm+bo9+eJ7WXfjiJfkclLgqlX3ec2cvVqAf
+NHisj18PEd/qtC64b+FnkgbsdHzWbo8HW5x4STkGXNnH+O3dvkWBX60MOfywfZFw
++yaz5mt7K+ft/V4UA7zKiAEFM+J1lND9/UMJnd0XMYYtcRQF8lmu4dlcjfbbAm0k
+VgoUEsizIeMPLrMj837uVloKKzIXmPsVsfMarP/MrX6TJfzdUhdm01pVO1g0wtHJ
+J3eYQsEnOI7RjL+uZDQvPWAnr71pvacn66PAJC1UPulEEla5lhd30RDItbJkngXp
+3UggW32ZOQt3Oc8P0eo9SCnBlHtCVr8wfxAbxCoPR9qIdX3azkQRqcKqGbBbPnkc
+hSCzeIofUkYGibfbZg4k1yY82xEqZuN7J1zycoGP4wyhXeRLTRWxfPR5dxxmQZaS
+67A1LWrYvAzF8Rd44VMRlI/Qk6zuBsL01j2dfBqit+le+viQmTYb3BpV+1kCAwEA
+AQKCAgAmSfX2LddyiXaLWo6DsePkp5tuihqvHqevl0TIAmPi+oMe4hqO9GueoZt9
+iYl9djILdkvrFkmbpKexpd1SeJhOBlPz8q4jfG+W5B41GOToIp7XSarHx1GS5I2U
+ltaiLX3KzVIIhDVDJF/hT7+yJKl7+DaiOu/nj5vEVMj8EvpinP1eBaYI9quHEi5W
+NKlrRjyikEBRQzZ7ulH3T1zXF87iYnVzUGLTH1aO5aW7q4YSA3KtSKmBQsjK9PrU
+DAefGY9iwgIkLOvtwm7UnbnVVZ3I0NO56WZ/e/SNzcrVLCg7F/eAhgbsBOQKAnbs
+4D35CuknJ9ZVcOYnLncNMw7IRMKULKYLAuLLN1X33y22qaVxYA42rq13mZrijlua
+CMQ2Ur+GNcq8OI3mRDO38yKeJ5b4885LQdlrXXyoGnSjlkU5n8U9Jw6q2rZGiWlk
+4Q71g+KUl0rtXSnFSIJLNTK6Cd3ETStxswLvvCvfLTrRQcO8f2SdVxblmsc9eCDs
+JUxz6Sahkpb9hsY8fozu6laXC/5Ezy0TinRgGjQM/DQqbXtFXgse56mDxzSho5oh
+Spy3X7Q/v4VUtrSKsEZEIEVWCpplzVULpHenCDbU58rHyEcS7ew+kwlfHC73iEhX
+HPujSIKvStO7yCEeY6IdhON8iVX34uvQeAgEe4+rehQHLZUg0QKCAQEA9AS3imKF
+yEt0yNRLcdXSqYkak+OM2kfhBBcLndCT7Terr6yluv/SkPGYjUbmr2XiygMv8IwO
+8f+KbWsNwYCaB22HVYVGL0oUYAlCvWhnia3Iwn6ZZuXuJv5mmfqt/GMlaIfohNLy
+zI2OlcpcAuRfNlenjNyd+inxwdXL28Z86kbabnUlijgqpu4KFOYOlxbTRv93IlfM
+Ico1pZkLS1glDMFLetF+IWq4zqpXrdgNUk1KX3sofOCfZQnlWFrrHbXJPCgPAtlv
+xP4dmJQgtWkWwxUlelfz34LcCUVX2aTlgKjuvgvyCt2ZPWixXbDtjsCBTn3xBhoY
+kDp2OyMC+d543QKCAQEAy11GpYOQvTMKbV07EmN9jTRYg7gRrxsT3Kd4Xy+NpIY8
+v6J5Keeppk9t6WBrJi2cQU/EoHcd3fRkWMnWMNorZDiCu34VG5bfa4pTqnSLdLC4
+/e5UHdHqCy9deAwhlHYWbAx0KnxXWGxkq05dXvQsVuOtAs528NcujnLpwDONQt5P
+e3RIZmOOjr+7rqGp3vA9SuNOINOQpeKxQT6GRGw4mlYofdwOPaE1wCsO8vQCNmCJ
+DEfdm+hWjTLAV2IBCfi5BKRsIAXrABPzkzDeLGDmaQkJTDpK8UQcrFnqItGeo+yl
+fDjxA0zAPWYGcyXcXbtvayX+zCk/SKwQABqUtaumrQKCAQEA0mdizwsGqd8OMsCC
+0QP64j4a0Zvqbqh9yCYK2Sfo9SkEe7SVLnm5WUtIK8EP1fs3ItK+ul454MZj2Nbv
+BINbzL3PbJk/HDV2/hveFS154UgcjD/XC9eEktDXLTvuW2ot7kUJ48V0n5YLdPMI
+hWHfCx9nlFkCSptyHp23aqhqOyOe4pFWLikh9c/Yl46K1BJVWKmcUtt7Y0NVIJWn
+HG9Dew0MhTkv1aaM9X4Bnh9l1SpZz5yFG7AfIGL5A0dZ5cNCYgF0eBN+gVBPuqk2
+ztVvUATizOwblwThr4jAKCU70sVXHj10lZPftwiXrt6I54brt/92HLnRpkMSgQk+
+Xq9KbQKCAQAXxPM47UPBmXGijr8UyyQlmPSvkJggi12q8LgVCA3aKQZ4r5jR2Q3v
+LmF+YZKkh7g3ugcValbHVoVUC2NJmnZv5FsDZx04eE3s1+Inji+ul+lHZM/YHGzq
+mcKnAWP7YkIEpv/850OeRi0OCL7JFmkITtwt88vbIouCgtPnbx8XrbxEhbbgoMpM
+zQQ2yRZ9xD6lviOnmpLRkMl/ArvWy39iKqfY7huMAIezylSY+QQ5LtdV5CB21JUp
+M8FfdUkBzVxyunUY2Rg6jhpuHcwaC8lihXfcvQN9Z6SiUHAZWb7dEg/VkSI6bIIb
+qw0d8FLtcbb4IxzA6CFJcTL9kB3JjiKRAoIBAQC15t3mQHb9iCM4P4U9fpR4syvN
+46vDMhtj3vejerzOro2R7UUCJDvT59DrCQvtKO/ZCyhdTyuyResu6r1vbwq3KWiB
+i0RIeW87cKgJRr6w+KivB+a805WfI9zNRz778b7ajEpBkOs4vRPWu6S1306tdvgM
+Dhj7GT9UFh/k7pNuoSbiuaPUqgZRP55nzgj/FoIN985wnxo/ugckSqZ1bFGFXhYt
+zfIdFvPkf1BlLCnLTE8yESsJ3P37Gfj2XRv9h2I2/8qAGZniKtbVWHlu+5LDJf6V
+x9VpDAH2ZQAqRC3za3gfTjMsglYi7mUDeMYlB4osURNt7jDtElEmsto7AAkI
+-----END RSA PRIVATE KEY-----
diff --git a/usb/1.0/default/apex/com.android.hardware.usb.pk8 b/usb/1.0/default/apex/com.android.hardware.usb.pk8
new file mode 100644
index 0000000..9f3f39b
--- /dev/null
+++ b/usb/1.0/default/apex/com.android.hardware.usb.pk8
Binary files differ
diff --git a/usb/1.0/default/apex/com.android.hardware.usb.x509.pem b/usb/1.0/default/apex/com.android.hardware.usb.x509.pem
new file mode 100644
index 0000000..210c30d
--- /dev/null
+++ b/usb/1.0/default/apex/com.android.hardware.usb.x509.pem
@@ -0,0 +1,34 @@
+-----BEGIN CERTIFICATE-----
+MIIF1TCCA70CFFEdsyLGoTRk+VIzqb6aDl1tXeuZMA0GCSqGSIb3DQEBCwUAMIGl
+MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
+bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
+MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTEhMB8GA1UEAwwYY29t
+LmFuZHJvaWQuaGFyZHdhcmUudXNiMCAXDTIxMTExNzIyMzAwM1oYDzQ3NTkxMDE0
+MjIzMDAzWjCBpTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAU
+BgNVBAcMDU1vdW50YWluIFZpZXcxEDAOBgNVBAoMB0FuZHJvaWQxEDAOBgNVBAsM
+B0FuZHJvaWQxIjAgBgkqhkiG9w0BCQEWE2FuZHJvaWRAYW5kcm9pZC5jb20xITAf
+BgNVBAMMGGNvbS5hbmRyb2lkLmhhcmR3YXJlLnVzYjCCAiIwDQYJKoZIhvcNAQEB
+BQADggIPADCCAgoCggIBAM2E0E9ubNU/or7r9UIcFrC4l7CeM0HwtwSjTUKV1Z9K
+7rPFoUPE3cQ+cResnWQay8IGnomLYptAIMe8sLCC83LwU1ucTihxX87qq2W3V14w
+U4AkqDzNvYqKiD3yz9WofKxcu7ut8+1O4Pvp11X8UXuy5kNzf8WGpGB04k6U6KtA
+q8+U8+4h9h1Uvhaa0AeG9Yp22LzRLTb3J+eCoGHJnjoXYsd9T/gvedyXKkuf0lWB
+b3Aor3/CQrpdCW2/iJbuASdBdfilpQShaagxy2wmQsYxnT8ZWf+tIDYjg3xqqVPl
+GChFwCQBdaTuLI/k9gbaXkSxuzRkp5wc/ELhYbkhIS25yefAF2C6num++AHQBh1+
+qO0fHztsK80c5cVoDPWu17/nP7y3QloRyLFUrL3hVW1RQaFwE2Hmv4H0UwVAsleU
+ZIsz2ifTjiSl/tnkFTx0I6BVk7T87QhO3WXN4v6VDYZKeD4gQYS0NfwplahejrFw
+s3EcwKgt6f0KlIpzoEQBmNQBXxsRgL31GWCwCszb7+VrTMzgUpO41R3PyewbeaZk
+S/SHyEOwyf0WIvnZhZ/5CNd9qirClu6jS8kdLvwC2qA25VqSPw126EX1e2xUqm02
+C/6c7JDVocuQhvsJOnnpZt68Iwgw9g/xLCLA9RszH9ccRctZqRnzHB1AjTrBOq0P
+AgMBAAEwDQYJKoZIhvcNAQELBQADggIBAELbSot2Io/JZIYLTxgeReI4lk1KUzf8
+fGlDNlRm+goxOHXWQgvXgiftwM9IOB+H+EtNHAA9Q6ojAmfRe6rZC4p0ZxWOamtR
+V+pQj0c6Zvx8HJPMQdyoHx538iNXM093s2wnf+QuACb3BnvkK7uuLGAlIzWdImtL
+DKKFN05nppViY04tGP5HgT57b7YGwdkEp6euCJcyWIKjlyEH/bwTWM8ws/Px6uhw
++5W2K7KrBsdRKPBF7qwXoS8Ak8pS5de9Xd7mbGBLaUtjsZ0pJbq0aFpuT0GbLWUm
+wiD5Ljq3ea/2GZxbHGiXQ2yNjFSd/jpuxDnnm99t7+HGw1v5Jld+hUVqXXfVNhWe
+hUKIv5TOk1nttNdsaLyDtxyt22JX7NnoPM0MqrkYwA8Xqrbv0VC8D/CVjiBC9Tce
+crhpCISNfQSkdEn/c+q/naFUvQy8oYqXkg1TjeGlcxwJOpGliYbbYT6VAwuI/ssI
+yX3Fkr8f5KhfN2aFnOpidknmLp9EyL2j5bxAtSD9xAHtczMn10uCUdLELjRB1L4f
+1qY+EjpIgK0NIFuEt9K5uZXirXq3K3eixKeJFNji3x/X8NgDALSdnT8JIlSg4DMg
+iWupLrQ9CSHMlgh5P43ALamiRIHQNqEwgj8OIGzsvQTSLbRjbPWYcDZa+Q1hosiA
+Fv7vjDI6oySM
+-----END CERTIFICATE-----
diff --git a/usb/1.0/default/apex/file_contexts b/usb/1.0/default/apex/file_contexts
new file mode 100644
index 0000000..bc84ac4
--- /dev/null
+++ b/usb/1.0/default/apex/file_contexts
@@ -0,0 +1,5 @@
+(/.*)?                                         u:object_r:vendor_file:s0
+# Permission XMLs
+/etc/permissions(/.*)?                         u:object_r:vendor_configs_file:s0
+# binary
+/bin/hw/android\.hardware\.usb@1\.0-service    u:object_r:hal_usb_default_exec:s0
\ No newline at end of file
diff --git a/usb/1.0/default/apex/manifest.json b/usb/1.0/default/apex/manifest.json
new file mode 100644
index 0000000..6a1095f
--- /dev/null
+++ b/usb/1.0/default/apex/manifest.json
@@ -0,0 +1,4 @@
+{
+  "name": "com.android.hardware.usb",
+  "version": 1
+}
diff --git a/usb/aidl/Android.bp b/usb/aidl/Android.bp
new file mode 100644
index 0000000..f71cacb
--- /dev/null
+++ b/usb/aidl/Android.bp
@@ -0,0 +1,42 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//       http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+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.usb",
+    vendor_available: true,
+    srcs: ["android/hardware/usb/*.aidl"],
+    stability: "vintf",
+    backend: {
+        cpp: {
+            enabled: false,
+        },
+        java: {
+            sdk_version: "module_current",
+        },
+        ndk: {
+            vndk: {
+                enabled: true,
+            },
+        },
+    },
+}
diff --git a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/ContaminantDetectionStatus.aidl b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/ContaminantDetectionStatus.aidl
new file mode 100644
index 0000000..24c6966
--- /dev/null
+++ b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/ContaminantDetectionStatus.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.usb;
+@VintfStability
+enum ContaminantDetectionStatus {
+  NOT_SUPPORTED = 0,
+  DISABLED = 1,
+  NOT_DETECTED = 2,
+  DETECTED = 3,
+}
diff --git a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/ContaminantProtectionMode.aidl b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/ContaminantProtectionMode.aidl
new file mode 100644
index 0000000..9979869
--- /dev/null
+++ b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/ContaminantProtectionMode.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.usb;
+@VintfStability
+enum ContaminantProtectionMode {
+  NONE = 0,
+  FORCE_SINK = 1,
+  FORCE_SOURCE = 2,
+  FORCE_DISABLE = 3,
+}
diff --git a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/ContaminantProtectionStatus.aidl b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/ContaminantProtectionStatus.aidl
new file mode 100644
index 0000000..9642261
--- /dev/null
+++ b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/ContaminantProtectionStatus.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.usb;
+@VintfStability
+enum ContaminantProtectionStatus {
+  NONE = 0,
+  FORCE_SINK = 1,
+  FORCE_SOURCE = 2,
+  FORCE_DISABLE = 3,
+  DISABLED = 4,
+}
diff --git a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/IUsb.aidl b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/IUsb.aidl
new file mode 100644
index 0000000..7513461
--- /dev/null
+++ b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/IUsb.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.usb;
+@VintfStability
+interface IUsb {
+  oneway void enableContaminantPresenceDetection(in String portName, in boolean enable, long transactionId);
+  oneway void enableUsbData(in String portName, boolean enable, long transactionId);
+  oneway void queryPortStatus(long transactionId);
+  oneway void setCallback(in android.hardware.usb.IUsbCallback callback);
+  oneway void switchRole(in String portName, in android.hardware.usb.PortRole role, long transactionId);
+}
diff --git a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/IUsbCallback.aidl b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/IUsbCallback.aidl
new file mode 100644
index 0000000..57be590
--- /dev/null
+++ b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/IUsbCallback.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.usb;
+@VintfStability
+interface IUsbCallback {
+  oneway void notifyPortStatusChange(in android.hardware.usb.PortStatus[] currentPortStatus, in android.hardware.usb.Status retval);
+  oneway void notifyRoleSwitchStatus(in String portName, in android.hardware.usb.PortRole newRole, in android.hardware.usb.Status retval, long transactionId);
+  oneway void notifyEnableUsbDataStatus(in String portName, boolean enable, in android.hardware.usb.Status retval, long transactionId);
+  oneway void notifyContaminantEnabledStatus(in String portName, boolean enable, in android.hardware.usb.Status retval, long transactionId);
+  oneway void notifyQueryPortStatus(in String portName, in android.hardware.usb.Status retval, long transactionId);
+}
diff --git a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortDataRole.aidl b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortDataRole.aidl
new file mode 100644
index 0000000..105b316
--- /dev/null
+++ b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortDataRole.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.usb;
+@VintfStability
+enum PortDataRole {
+  NONE = 0,
+  HOST = 1,
+  DEVICE = 2,
+}
diff --git a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortMode.aidl b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortMode.aidl
new file mode 100644
index 0000000..34e4334
--- /dev/null
+++ b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortMode.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.usb;
+@VintfStability
+enum PortMode {
+  NONE = 0,
+  UFP = 1,
+  DFP = 2,
+  DRP = 3,
+  AUDIO_ACCESSORY = 4,
+  DEBUG_ACCESSORY = 5,
+}
diff --git a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortPowerRole.aidl b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortPowerRole.aidl
new file mode 100644
index 0000000..0e6f3fb
--- /dev/null
+++ b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortPowerRole.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.usb;
+@VintfStability
+enum PortPowerRole {
+  NONE = 0,
+  SOURCE = 1,
+  SINK = 2,
+}
diff --git a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortRole.aidl b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortRole.aidl
new file mode 100644
index 0000000..c66aecc
--- /dev/null
+++ b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortRole.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.usb;
+@VintfStability
+union PortRole {
+  android.hardware.usb.PortPowerRole powerRole = android.hardware.usb.PortPowerRole.NONE;
+  android.hardware.usb.PortDataRole dataRole;
+  android.hardware.usb.PortMode mode;
+}
diff --git a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortStatus.aidl b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortStatus.aidl
new file mode 100644
index 0000000..78dcfac
--- /dev/null
+++ b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortStatus.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.usb;
+@VintfStability
+parcelable PortStatus {
+  String portName;
+  android.hardware.usb.PortDataRole currentDataRole = android.hardware.usb.PortDataRole.NONE;
+  android.hardware.usb.PortPowerRole currentPowerRole = android.hardware.usb.PortPowerRole.NONE;
+  android.hardware.usb.PortMode currentMode = android.hardware.usb.PortMode.NONE;
+  boolean canChangeMode;
+  boolean canChangeDataRole;
+  boolean canChangePowerRole;
+  android.hardware.usb.PortMode[] supportedModes;
+  android.hardware.usb.ContaminantProtectionMode[] supportedContaminantProtectionModes;
+  boolean supportsEnableContaminantPresenceProtection;
+  android.hardware.usb.ContaminantProtectionStatus contaminantProtectionStatus = android.hardware.usb.ContaminantProtectionStatus.NONE;
+  boolean supportsEnableContaminantPresenceDetection;
+  android.hardware.usb.ContaminantDetectionStatus contaminantDetectionStatus = android.hardware.usb.ContaminantDetectionStatus.NOT_SUPPORTED;
+  boolean usbDataEnabled;
+}
diff --git a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/Status.aidl b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/Status.aidl
new file mode 100644
index 0000000..f28fc2a
--- /dev/null
+++ b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/Status.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.usb;
+@Backing(type="int") @VintfStability
+enum Status {
+  SUCCESS = 0,
+  ERROR = 1,
+  INVALID_ARGUMENT = 2,
+  UNRECOGNIZED_ROLE = 3,
+  NOT_SUPPORTED = 4,
+}
diff --git a/usb/aidl/android/hardware/usb/ContaminantDetectionStatus.aidl b/usb/aidl/android/hardware/usb/ContaminantDetectionStatus.aidl
new file mode 100644
index 0000000..d9bc576
--- /dev/null
+++ b/usb/aidl/android/hardware/usb/ContaminantDetectionStatus.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.usb;
+
+@VintfStability
+enum ContaminantDetectionStatus {
+    /**
+     * Contaminant presence detection is not supported.
+     */
+    NOT_SUPPORTED = 0,
+    /**
+     * Contaminant presence detection is supported but disabled.
+     */
+    DISABLED = 1,
+    /**
+     * Contaminant presence detection is enabled and contaminant not detected.
+     */
+    NOT_DETECTED = 2,
+    /**
+     * Contaminant presence detection is enabled and contaminant detected.
+     */
+    DETECTED = 3,
+}
diff --git a/usb/aidl/android/hardware/usb/ContaminantProtectionMode.aidl b/usb/aidl/android/hardware/usb/ContaminantProtectionMode.aidl
new file mode 100644
index 0000000..47c073d
--- /dev/null
+++ b/usb/aidl/android/hardware/usb/ContaminantProtectionMode.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.usb;
+
+@VintfStability
+enum ContaminantProtectionMode {
+    /**
+     * No action performed upon detection of contaminant presence.
+     */
+    NONE = 0,
+    /**
+     * Upon detection of contaminant presence, Port is forced to sink only
+     * mode where a port shall only detect chargers until contaminant presence
+     * is no longer detected.
+     */
+    FORCE_SINK = 1,
+    /**
+     * Upon detection of contaminant presence, Port is forced to source only
+     * mode where a port shall only detect usb accessories such as headsets
+     * until contaminant presence is no longer detected.
+     */
+    FORCE_SOURCE = 2,
+    /**
+     * Upon detection of contaminant presence, port is disabled until contaminant
+     * presence is no longer detected. In the disabled state port will
+     * not respond to connection of chargers or usb accessories.
+     */
+    FORCE_DISABLE = 3,
+}
diff --git a/usb/aidl/android/hardware/usb/ContaminantProtectionStatus.aidl b/usb/aidl/android/hardware/usb/ContaminantProtectionStatus.aidl
new file mode 100644
index 0000000..c4fa979
--- /dev/null
+++ b/usb/aidl/android/hardware/usb/ContaminantProtectionStatus.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.usb;
+
+import android.hardware.usb.ContaminantProtectionMode;
+
+@VintfStability
+enum ContaminantProtectionStatus {
+    /**
+     * No action performed upon detection of contaminant presence.
+     */
+    NONE = 0,
+    /**
+     * Upon detection of contaminant presence, Port is forced to sink only
+     * mode where a port shall only detect chargers until contaminant presence
+     * is no longer detected.
+     */
+    FORCE_SINK = 1,
+    /**
+     * Upon detection of contaminant presence, Port is forced to source only
+     * mode where a port shall only detect usb accessories such as headsets
+     * until contaminant presence is no longer detected.
+     */
+    FORCE_SOURCE = 2,
+    /**
+     * Upon detection of contaminant presence, port is disabled until contaminant
+     * presence is no longer detected. In the disabled state port will
+     * not respond to connection of chargers or usb accessories.
+     */
+    FORCE_DISABLE = 3,
+    /**
+     * Client disabled cotaminant protection by calling
+     * enableContaminantPresencePortProtection set to false. Low level drivers should
+     * not autmomously take any corrective action when contaminant presence is detected.
+     */
+    DISABLED = 4,
+}
diff --git a/usb/aidl/android/hardware/usb/IUsb.aidl b/usb/aidl/android/hardware/usb/IUsb.aidl
new file mode 100644
index 0000000..9a8f000
--- /dev/null
+++ b/usb/aidl/android/hardware/usb/IUsb.aidl
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.usb;
+
+import android.hardware.usb.IUsbCallback;
+import android.hardware.usb.PortRole;
+
+@VintfStability
+oneway interface IUsb {
+    /**
+     * When supportsEnableContaminantPresenceDetection is true,
+     * enableContaminantPresenceDetection enables/disables contaminant
+     * presence detection algorithm. Calling enableContaminantPresenceDetection
+     * when supportsEnableContaminantPresenceDetection is false does
+     * not have any effect.
+     * Change in contantaminant presence status should be notified to the
+     * client via notifyPortStatusChange through PortStatus.
+     *
+     * @param portName name of the port.
+     * @param enable true Enable contaminant presence detection algorithm.
+     *               false Disable contaminant presence detection algorithm.
+     * @param transactionId ID to be used when invoking the callback.
+     */
+    void enableContaminantPresenceDetection(in String portName, in boolean enable, long transactionId);
+
+    /**
+     * This function is used to enable/disable USB data controller.
+     *
+     * @param portName Name of the port.
+     * @param enable   true Enable USB data signaling.
+     *                 false Disable USB data signaling.
+     * @param transactionId ID to be used when invoking the callback.
+     *
+     */
+    void enableUsbData(in String portName, boolean enable, long transactionId);
+
+    /**
+     * This functions is used to request the hal for the current status
+     * status of the Type-C ports. The result of the query would be sent
+     * through the IUsbCallback object's notifyRoleSwitchStatus
+     * to the caller. This api would would let the caller know of the number
+     * of type-c ports that are present and their connection status through the
+     * PortStatus type.
+     * @param transactionId ID to be used when invoking the callback.
+     */
+    void queryPortStatus(long transactionId);
+
+    /**
+     * This function is used to register a callback function which is
+     * called by the HAL to inform the client of port status updates and
+     * result of the requested operation. Please refer IUsbCallback for
+     * complete description of when each of the IUsbCallback's interface
+     * methods is expected to be called.
+     *
+     * @param callback IUsbCallback object used to convey status to the
+     * userspace.
+     */
+    void setCallback(in IUsbCallback callback);
+
+    /**
+     * This function is used to change the port role of a specific port.
+     * For example, when DR_SWAP or PR_SWAP is supported.
+     * The status of the role switch will be informed through IUsbCallback
+     * object's notifyPortStatusChange method.
+     *
+     * @param portName name of the port for which the role has to be changed
+     * @param role the new port role.
+     * @param transactionId ID to be used when invoking the callback.
+     */
+    void switchRole(in String portName, in PortRole role, long transactionId);
+}
diff --git a/usb/aidl/android/hardware/usb/IUsbCallback.aidl b/usb/aidl/android/hardware/usb/IUsbCallback.aidl
new file mode 100644
index 0000000..232a15b
--- /dev/null
+++ b/usb/aidl/android/hardware/usb/IUsbCallback.aidl
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.usb;
+
+import android.hardware.usb.PortRole;
+import android.hardware.usb.PortStatus;
+import android.hardware.usb.Status;
+
+/**
+ * Callback object used for all the IUsb async methods which expects a result.
+ * Caller is expected to register the callback object using setCallback method
+ * to receive updates on the PortStatus.
+ */
+@VintfStability
+oneway interface IUsbCallback {
+    /**
+     * Used to convey the current port status to the caller.
+     * Must be called either when PortState changes due to the port partner or
+     * when caller requested for the PortStatus update through queryPortStatus.
+     *
+     * @param currentPortStatus describes the status of all the USB ports in the
+     *                          device.
+     * @param retval SUCCESS when the required information was enquired form
+     *               kernel and the PortStatus object was built.
+     *               ERROR otherwise.
+     */
+    void notifyPortStatusChange(in PortStatus[] currentPortStatus, in Status retval);
+
+    /**
+     * Used to notify the result of the switchRole call to the caller.
+     *
+     * @param portName name of the port for which the roleswap is requested.
+     * @param newRole the new role requested by the caller.
+     * @param retval SUCCESS if the role switch succeeded. FAILURE otherwise.
+     * @param transactionId  transactionId sent during switchRole request.
+     */
+    void notifyRoleSwitchStatus(in String portName, in PortRole newRole, in Status retval,
+            long transactionId);
+
+    /**
+     * Used to notify the result of notifyEnableUsbDataStatus call to the caller.
+     *
+     * @param portName name of the port for which the enableUsbData is requested.
+     * @param enable true when usb data is enabled.
+     *               false when usb data is disabled.
+     * @param retval SUCCESS if current request succeeded. FAILURE otherwise.
+     * @param transactionId transactionId sent during enableUsbData request.
+     */
+    void notifyEnableUsbDataStatus(in String portName, boolean enable, in Status retval,
+            long transactionId);
+
+    /**
+     * Used to notify the result of enableContaminantPresenceDetection.
+     *
+     * @param portName name of the port for which contaminant detection is enabled/disabled.
+     * @param enable true when contaminant detection is enabled.
+     *               false when disabled.
+     * @param retval SUCCESS if the request for enabling/disabling contamiant detection succeeds.
+     *               FAILURE otherwise.
+     * @param transactionId transactionId sent during queryPortStatus request
+     */
+    void notifyContaminantEnabledStatus(in String portName, boolean enable, in Status retval,
+            long transactionId);
+
+    /**
+     * Used to notify the request to query port status.
+     *
+     * @param portName name of the port for which port status is queried.
+     * @param retval SUCCESS if the port query succeeded. FAILURE otherwise.
+     * @param transactionId transactionId sent during queryPortStatus request
+     */
+    void notifyQueryPortStatus(in String portName, in Status retval, long transactionId);
+}
diff --git a/usb/aidl/android/hardware/usb/PortDataRole.aidl b/usb/aidl/android/hardware/usb/PortDataRole.aidl
new file mode 100644
index 0000000..a69f977
--- /dev/null
+++ b/usb/aidl/android/hardware/usb/PortDataRole.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.usb;
+
+@VintfStability
+enum PortDataRole {
+    /**
+     * Indicates that the port does not have a data role.
+     * In case of DRP, the current data role of the port is only resolved
+     * when the type-c handshake happens.
+     */
+    NONE = 0,
+    /**
+     * Indicates that the port is acting as a host for data.
+     */
+    HOST = 1,
+    /**
+     * Indicated that the port is acting as a device for data.
+     */
+    DEVICE = 2,
+}
diff --git a/usb/aidl/android/hardware/usb/PortMode.aidl b/usb/aidl/android/hardware/usb/PortMode.aidl
new file mode 100644
index 0000000..399f0eb
--- /dev/null
+++ b/usb/aidl/android/hardware/usb/PortMode.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.usb;
+
+import android.hardware.usb.PortMode;
+
+@VintfStability
+enum PortMode {
+    /**
+     * Indicates that the port does not have a mode.
+     * In case of DRP, the current mode of the port is only resolved
+     * when the type-c handshake happens.
+     */
+    NONE = 0,
+    /**
+     * Indicates that port can only act as device for data and sink for power.
+     */
+    UFP = 1,
+    /**
+     * Indicates the port can only act as host for data and source for power.
+     */
+    DFP = 2,
+    /**
+     * Indicates can either act as UFP or DFP at a given point of time.
+     */
+    DRP = 3,
+    /*
+     * Indicates that the port supports Audio Accessory mode.
+     */
+    AUDIO_ACCESSORY = 4,
+    /*
+     * Indicates that the port supports Debug Accessory mode.
+     */
+    DEBUG_ACCESSORY = 5,
+}
diff --git a/usb/aidl/android/hardware/usb/PortPowerRole.aidl b/usb/aidl/android/hardware/usb/PortPowerRole.aidl
new file mode 100644
index 0000000..ae3dc47
--- /dev/null
+++ b/usb/aidl/android/hardware/usb/PortPowerRole.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.usb;
+
+@VintfStability
+enum PortPowerRole {
+    /**
+     * Indicates that the port does not have a power role.
+     * In case of DRP, the current power role of the port is only resolved
+     * when the type-c handshake happens.
+     */
+    NONE = 0,
+    /**
+     * Indicates that the port is supplying power to the other port.
+     */
+    SOURCE = 1,
+    /**
+     * Indicates that the port is sinking power from the other port.
+     */
+    SINK = 2,
+}
diff --git a/usb/aidl/android/hardware/usb/PortRole.aidl b/usb/aidl/android/hardware/usb/PortRole.aidl
new file mode 100644
index 0000000..e0429c8
--- /dev/null
+++ b/usb/aidl/android/hardware/usb/PortRole.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.usb;
+
+import android.hardware.usb.PortDataRole;
+import android.hardware.usb.PortMode;
+import android.hardware.usb.PortPowerRole;
+
+/**
+ * Used as a container to send port role information.
+ */
+@VintfStability
+union PortRole {
+    PortPowerRole powerRole = PortPowerRole.NONE;
+    PortDataRole dataRole;
+    PortMode mode;
+}
diff --git a/usb/aidl/android/hardware/usb/PortStatus.aidl b/usb/aidl/android/hardware/usb/PortStatus.aidl
new file mode 100644
index 0000000..8afe009
--- /dev/null
+++ b/usb/aidl/android/hardware/usb/PortStatus.aidl
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.usb;
+
+import android.hardware.usb.ContaminantDetectionStatus;
+import android.hardware.usb.ContaminantProtectionMode;
+import android.hardware.usb.ContaminantProtectionStatus;
+import android.hardware.usb.PortDataRole;
+import android.hardware.usb.PortMode;
+import android.hardware.usb.PortPowerRole;
+
+@VintfStability
+parcelable PortStatus {
+    /**
+     * Name of the port.
+     * Used as the port's id by the caller.
+     */
+    String portName;
+    /**
+     * Data role of the port.
+     */
+    PortDataRole currentDataRole = PortDataRole.NONE;
+    /**
+     * Power Role of thte port.
+     */
+    PortPowerRole currentPowerRole = PortPowerRole.NONE;
+    /**
+     * Mode in which the port is connected.
+     * Can be UFP or DFP or AUDIO_ACCESSORY or
+     * DEBUG_ACCESSORY.
+     */
+    PortMode currentMode = PortMode.NONE;
+    /**
+     * True indicates that the port's mode can
+     * be changed. False otherwise.
+     */
+    boolean canChangeMode;
+    /**
+     * True indicates that the port's data role
+     * can be changed. False otherwise.
+     * For example, true if Type-C PD PD_SWAP
+     * is supported.
+     */
+    boolean canChangeDataRole;
+    /**
+     * True indicates that the port's power role
+     * can be changed. False otherwise.
+     * For example, true if Type-C PD PR_SWAP
+     * is supported.
+     */
+    boolean canChangePowerRole;
+    /**
+     * Identifies the type of the local port.
+     *
+     * UFP - Indicates that port can only act as device for
+     *       data and sink for power.
+     * DFP - Indicates the port can only act as host for data
+     *       and source for power.
+     * DRP - Indicates can either act as UFP or DFP at a
+     *       given point of time.
+     * AUDIO_ACCESSORY -  Indicates that the port supports
+     *                    Audio Accessory mode.
+     * DEBUG_ACCESSORY - Indicates that the port supports
+     *                   Debug Accessory mode.
+     */
+    PortMode[] supportedModes;
+    /**
+     * Contaminant presence protection modes supported by the port.
+     */
+    ContaminantProtectionMode[] supportedContaminantProtectionModes;
+    /**
+     * Client can enable/disable contaminant presence protection through
+     * enableContaminantPresenceProtection when true.
+     */
+    boolean supportsEnableContaminantPresenceProtection;
+    /**
+     * Contaminant presence protection modes currently active for the port.
+     */
+    ContaminantProtectionStatus contaminantProtectionStatus = ContaminantProtectionStatus.NONE;
+    /**
+     * Client can enable/disable contaminant presence detection through
+     * enableContaminantPresenceDetection when true.
+     */
+    boolean supportsEnableContaminantPresenceDetection;
+    /**
+     * Current status of contaminant detection algorithm.
+     */
+    ContaminantDetectionStatus contaminantDetectionStatus = ContaminantDetectionStatus.NOT_SUPPORTED;
+    /**
+     * UsbData status of the port.
+     */
+    boolean usbDataEnabled;
+}
diff --git a/usb/aidl/android/hardware/usb/Status.aidl b/usb/aidl/android/hardware/usb/Status.aidl
new file mode 100644
index 0000000..468ba4a
--- /dev/null
+++ b/usb/aidl/android/hardware/usb/Status.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.usb;
+
+@VintfStability
+@Backing(type="int")
+enum Status {
+    SUCCESS = 0,
+    /**
+     * error value when the HAL operation fails for reasons not listed here.
+     */
+    ERROR = 1,
+    /**
+     * error value returned when input argument is invalid.
+     */
+    INVALID_ARGUMENT = 2,
+    /**
+     * error value returned when role string is unrecognized.
+     */
+    UNRECOGNIZED_ROLE = 3,
+    /**
+     * Error value returned when the operation is not supported.
+     */
+    NOT_SUPPORTED = 4,
+}
diff --git a/usb/aidl/conversion.log b/usb/aidl/conversion.log
new file mode 100644
index 0000000..c090446
--- /dev/null
+++ b/usb/aidl/conversion.log
@@ -0,0 +1,11 @@
+Notes relating to hidl2aidl conversion of android.hardware.usb@1.3 to android.hardware.usb (if any) follow:
+Unhandled comments from android.hardware.usb@1.1::types follow. Consider using hidl-lint to locate these and fixup as many as possible.
+ // NOTE: suffix '_1_1' is for legacy ABI compatibility. It cannot be
+ // changed to 'PortMode' which the convention dictates.
+ // NOTE: suffix '_1_1' is for legacy ABI compatibility. It cannot be
+ // changed to 'PortStatus' which the convention dictates.
+
+An unknown named type was found in translation: android.hardware.usb@1.0::PortStatus
+An unknown named type was found in translation: android.hardware.usb@1.0::PortStatus
+An unknown named type was found in translation: android.hardware.usb@1.0::PortStatus
+END OF LOG
diff --git a/usb/aidl/default/Android.bp b/usb/aidl/default/Android.bp
new file mode 100644
index 0000000..7cb2822
--- /dev/null
+++ b/usb/aidl/default/Android.bp
@@ -0,0 +1,44 @@
+//
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+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.usb-service.example",
+    relative_install_path: "hw",
+    init_rc: ["android.hardware.usb-service.example.rc"],
+    vintf_fragments: ["android.hardware.usb-service.example.xml"],
+    vendor: true,
+    srcs: [
+        "service.cpp",
+        "Usb.cpp",
+    ],
+    shared_libs: [
+        "android.hardware.usb-V1-ndk",
+        "libbase",
+        "libbinder_ndk",
+	"libcutils",
+        "liblog",
+        "libutils",
+    ],
+}
diff --git a/usb/aidl/default/Usb.cpp b/usb/aidl/default/Usb.cpp
new file mode 100644
index 0000000..1105376
--- /dev/null
+++ b/usb/aidl/default/Usb.cpp
@@ -0,0 +1,693 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.usb.aidl-service"
+
+#include <aidl/android/hardware/usb/PortRole.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android-base/strings.h>
+#include <assert.h>
+#include <dirent.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <chrono>
+#include <regex>
+#include <thread>
+#include <unordered_map>
+
+#include <cutils/uevent.h>
+#include <sys/epoll.h>
+#include <utils/Errors.h>
+#include <utils/StrongPointer.h>
+
+#include "Usb.h"
+
+using android::base::GetProperty;
+using android::base::Trim;
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace usb {
+
+constexpr char kTypecPath[] = "/sys/class/typec/";
+constexpr char kDataRoleNode[] = "/data_role";
+constexpr char kPowerRoleNode[] = "/power_role";
+
+// Set by the signal handler to destroy the thread
+volatile bool destroyThread;
+
+void queryVersionHelper(android::hardware::usb::Usb *usb,
+                        std::vector<PortStatus> *currentPortStatus);
+
+ScopedAStatus Usb::enableUsbData(const string& in_portName, bool in_enable, int64_t in_transactionId) {
+    std::vector<PortStatus> currentPortStatus;
+
+    pthread_mutex_lock(&mLock);
+    if (mCallback != NULL) {
+        ScopedAStatus ret = mCallback->notifyEnableUsbDataStatus(
+            in_portName, true, in_enable ? Status::SUCCESS : Status::ERROR, in_transactionId);
+        if (!ret.isOk())
+            ALOGE("notifyEnableUsbDataStatus error %s", ret.getDescription().c_str());
+    } else {
+        ALOGE("Not notifying the userspace. Callback is not set");
+    }
+    pthread_mutex_unlock(&mLock);
+    queryVersionHelper(this, &currentPortStatus);
+
+    return ScopedAStatus::ok();
+}
+
+Status queryMoistureDetectionStatus(std::vector<PortStatus> *currentPortStatus) {
+    string enabled, status, path, DetectedPath;
+
+    for (int i = 0; i < currentPortStatus->size(); i++) {
+        (*currentPortStatus)[i].supportedContaminantProtectionModes
+                .push_back(ContaminantProtectionMode::NONE);
+        (*currentPortStatus)[i].contaminantProtectionStatus
+                = ContaminantProtectionStatus::NONE;
+        (*currentPortStatus)[i].contaminantDetectionStatus
+                = ContaminantDetectionStatus::NOT_SUPPORTED;
+        (*currentPortStatus)[i].supportsEnableContaminantPresenceDetection = false;
+        (*currentPortStatus)[i].supportsEnableContaminantPresenceProtection = false;
+    }
+
+    return Status::SUCCESS;
+}
+
+string appendRoleNodeHelper(const string &portName, PortRole::Tag tag) {
+    string node(kTypecPath + portName);
+
+    switch (tag) {
+        case PortRole::dataRole:
+            return node + kDataRoleNode;
+        case PortRole::powerRole:
+            return node + kPowerRoleNode;
+        case PortRole::mode:
+            return node + "/port_type";
+        default:
+            return "";
+    }
+}
+
+string convertRoletoString(PortRole role) {
+    if (role.getTag() == PortRole::powerRole) {
+        if (role.get<PortRole::powerRole>() == PortPowerRole::SOURCE)
+            return "source";
+        else if (role.get<PortRole::powerRole>() == PortPowerRole::SINK)
+            return "sink";
+    } else if (role.getTag() == PortRole::dataRole) {
+        if (role.get<PortRole::dataRole>() == PortDataRole::HOST)
+            return "host";
+        if (role.get<PortRole::dataRole>() == PortDataRole::DEVICE)
+            return "device";
+    } else if (role.getTag() == PortRole::mode) {
+        if (role.get<PortRole::mode>() == PortMode::UFP)
+            return "sink";
+        if (role.get<PortRole::mode>() == PortMode::DFP)
+            return "source";
+    }
+    return "none";
+}
+
+void extractRole(string *roleName) {
+    std::size_t first, last;
+
+    first = roleName->find("[");
+    last = roleName->find("]");
+
+    if (first != string::npos && last != string::npos) {
+        *roleName = roleName->substr(first + 1, last - first - 1);
+    }
+}
+
+void switchToDrp(const string &portName) {
+    string filename = appendRoleNodeHelper(string(portName.c_str()), PortRole::mode);
+    FILE *fp;
+
+    if (filename != "") {
+        fp = fopen(filename.c_str(), "w");
+        if (fp != NULL) {
+            int ret = fputs("dual", fp);
+            fclose(fp);
+            if (ret == EOF)
+                ALOGE("Fatal: Error while switching back to drp");
+        } else {
+            ALOGE("Fatal: Cannot open file to switch back to drp");
+        }
+    } else {
+        ALOGE("Fatal: invalid node type");
+    }
+}
+
+bool switchMode(const string &portName, const PortRole &in_role, struct Usb *usb) {
+    string filename = appendRoleNodeHelper(string(portName.c_str()), in_role.getTag());
+    string written;
+    FILE *fp;
+    bool roleSwitch = false;
+
+    if (filename == "") {
+        ALOGE("Fatal: invalid node type");
+        return false;
+    }
+
+    fp = fopen(filename.c_str(), "w");
+    if (fp != NULL) {
+        // Hold the lock here to prevent loosing connected signals
+        // as once the file is written the partner added signal
+        // can arrive anytime.
+        pthread_mutex_lock(&usb->mPartnerLock);
+        usb->mPartnerUp = false;
+        int ret = fputs(convertRoletoString(in_role).c_str(), fp);
+        fclose(fp);
+
+        if (ret != EOF) {
+            struct timespec to;
+            struct timespec now;
+
+        wait_again:
+            clock_gettime(CLOCK_MONOTONIC, &now);
+            to.tv_sec = now.tv_sec + PORT_TYPE_TIMEOUT;
+            to.tv_nsec = now.tv_nsec;
+
+            int err = pthread_cond_timedwait(&usb->mPartnerCV, &usb->mPartnerLock, &to);
+            // There are no uevent signals which implies role swap timed out.
+            if (err == ETIMEDOUT) {
+                ALOGI("uevents wait timedout");
+                // Validity check.
+            } else if (!usb->mPartnerUp) {
+                goto wait_again;
+                // Role switch succeeded since usb->mPartnerUp is true.
+            } else {
+                roleSwitch = true;
+            }
+        } else {
+            ALOGI("Role switch failed while wrting to file");
+        }
+        pthread_mutex_unlock(&usb->mPartnerLock);
+    }
+
+    if (!roleSwitch)
+        switchToDrp(string(portName.c_str()));
+
+    return roleSwitch;
+}
+
+Usb::Usb()
+    : mLock(PTHREAD_MUTEX_INITIALIZER),
+      mRoleSwitchLock(PTHREAD_MUTEX_INITIALIZER),
+      mPartnerLock(PTHREAD_MUTEX_INITIALIZER),
+      mPartnerUp(false)
+{
+    pthread_condattr_t attr;
+    if (pthread_condattr_init(&attr)) {
+        ALOGE("pthread_condattr_init failed: %s", strerror(errno));
+        abort();
+    }
+    if (pthread_condattr_setclock(&attr, CLOCK_MONOTONIC)) {
+        ALOGE("pthread_condattr_setclock failed: %s", strerror(errno));
+        abort();
+    }
+    if (pthread_cond_init(&mPartnerCV, &attr)) {
+        ALOGE("pthread_cond_init failed: %s", strerror(errno));
+        abort();
+    }
+    if (pthread_condattr_destroy(&attr)) {
+        ALOGE("pthread_condattr_destroy failed: %s", strerror(errno));
+        abort();
+    }
+}
+
+ScopedAStatus Usb::switchRole(const string& in_portName,
+        const PortRole& in_role, int64_t in_transactionId) {
+    string filename = appendRoleNodeHelper(string(in_portName.c_str()), in_role.getTag());
+    string written;
+    FILE *fp;
+    bool roleSwitch = false;
+
+    if (filename == "") {
+        ALOGE("Fatal: invalid node type");
+        return ScopedAStatus::ok();
+    }
+
+    pthread_mutex_lock(&mRoleSwitchLock);
+
+    ALOGI("filename write: %s role:%s", filename.c_str(), convertRoletoString(in_role).c_str());
+
+    if (in_role.getTag() == PortRole::mode) {
+        roleSwitch = switchMode(in_portName, in_role, this);
+    } else {
+        fp = fopen(filename.c_str(), "w");
+        if (fp != NULL) {
+            int ret = fputs(convertRoletoString(in_role).c_str(), fp);
+            fclose(fp);
+            if ((ret != EOF) && ReadFileToString(filename, &written)) {
+                written = Trim(written);
+                extractRole(&written);
+                ALOGI("written: %s", written.c_str());
+                if (written == convertRoletoString(in_role)) {
+                    roleSwitch = true;
+                } else {
+                    ALOGE("Role switch failed");
+                }
+            } else {
+                ALOGE("failed to update the new role");
+            }
+        } else {
+            ALOGE("fopen failed");
+        }
+    }
+
+    pthread_mutex_lock(&mLock);
+    if (mCallback != NULL) {
+         ScopedAStatus ret = mCallback->notifyRoleSwitchStatus(
+            in_portName, in_role, roleSwitch ? Status::SUCCESS : Status::ERROR, in_transactionId);
+        if (!ret.isOk())
+            ALOGE("RoleSwitchStatus error %s", ret.getDescription().c_str());
+    } else {
+        ALOGE("Not notifying the userspace. Callback is not set");
+    }
+    pthread_mutex_unlock(&mLock);
+    pthread_mutex_unlock(&mRoleSwitchLock);
+
+    return ScopedAStatus::ok();
+}
+
+Status getAccessoryConnected(const string &portName, string *accessory) {
+    string filename = kTypecPath + portName + "-partner/accessory_mode";
+
+    if (!ReadFileToString(filename, accessory)) {
+        ALOGE("getAccessoryConnected: Failed to open filesystem node: %s", filename.c_str());
+        return Status::ERROR;
+    }
+    *accessory = Trim(*accessory);
+
+    return Status::SUCCESS;
+}
+
+Status getCurrentRoleHelper(const string &portName, bool connected, PortRole *currentRole) {
+    string filename;
+    string roleName;
+    string accessory;
+
+    // Mode
+
+    if (currentRole->getTag() == PortRole::powerRole) {
+        filename = kTypecPath + portName + kPowerRoleNode;
+        currentRole->set<PortRole::powerRole>(PortPowerRole::NONE);
+    } else if (currentRole->getTag() == PortRole::dataRole) {
+        filename = kTypecPath + portName + kDataRoleNode;
+        currentRole->set<PortRole::dataRole>(PortDataRole::NONE);
+    } else if (currentRole->getTag() == PortRole::mode) {
+        filename = kTypecPath + portName + kDataRoleNode;
+        currentRole->set<PortRole::mode>(PortMode::NONE);
+    } else {
+        return Status::ERROR;
+    }
+
+    if (!connected)
+        return Status::SUCCESS;
+
+    if (currentRole->getTag() == PortRole::mode) {
+        if (getAccessoryConnected(portName, &accessory) != Status::SUCCESS) {
+            return Status::ERROR;
+        }
+        if (accessory == "analog_audio") {
+            currentRole->set<PortRole::mode>(PortMode::AUDIO_ACCESSORY);
+            return Status::SUCCESS;
+        } else if (accessory == "debug") {
+            currentRole->set<PortRole::mode>(PortMode::DEBUG_ACCESSORY);
+            return Status::SUCCESS;
+        }
+    }
+
+    if (!ReadFileToString(filename, &roleName)) {
+        ALOGE("getCurrentRole: Failed to open filesystem node: %s", filename.c_str());
+        return Status::ERROR;
+    }
+
+    roleName = Trim(roleName);
+    extractRole(&roleName);
+
+    if (roleName == "source") {
+        currentRole->set<PortRole::powerRole>(PortPowerRole::SOURCE);
+    } else if (roleName == "sink") {
+        currentRole->set<PortRole::powerRole>(PortPowerRole::SINK);
+    } else if (roleName == "host") {
+        if (currentRole->getTag() == PortRole::dataRole)
+            currentRole->set<PortRole::dataRole>(PortDataRole::HOST);
+        else
+            currentRole->set<PortRole::mode>(PortMode::DFP);
+    } else if (roleName == "device") {
+        if (currentRole->getTag() == PortRole::dataRole)
+            currentRole->set<PortRole::dataRole>(PortDataRole::DEVICE);
+        else
+            currentRole->set<PortRole::mode>(PortMode::UFP);
+    } else if (roleName != "none") {
+        /* case for none has already been addressed.
+         * so we check if the role isn't none.
+         */
+        return Status::UNRECOGNIZED_ROLE;
+    }
+
+    return Status::SUCCESS;
+}
+
+Status getTypeCPortNamesHelper(std::unordered_map<string, bool> *names) {
+    DIR *dp;
+
+    dp = opendir(kTypecPath);
+    if (dp != NULL) {
+        struct dirent *ep;
+
+        while ((ep = readdir(dp))) {
+            if (ep->d_type == DT_LNK) {
+                if (string::npos == string(ep->d_name).find("-partner")) {
+                    std::unordered_map<string, bool>::const_iterator portName =
+                        names->find(ep->d_name);
+                    if (portName == names->end()) {
+                        names->insert({ep->d_name, false});
+                    }
+                } else {
+                    (*names)[std::strtok(ep->d_name, "-")] = true;
+                }
+            }
+        }
+        closedir(dp);
+        return Status::SUCCESS;
+    }
+
+    ALOGE("Failed to open /sys/class/typec");
+    return Status::ERROR;
+}
+
+bool canSwitchRoleHelper(const string &portName) {
+    string filename = kTypecPath + portName + "-partner/supports_usb_power_delivery";
+    string supportsPD;
+
+    if (ReadFileToString(filename, &supportsPD)) {
+        supportsPD = Trim(supportsPD);
+        if (supportsPD == "yes") {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+Status getPortStatusHelper(std::vector<PortStatus> *currentPortStatus) {
+    std::unordered_map<string, bool> names;
+    Status result = getTypeCPortNamesHelper(&names);
+    int i = -1;
+
+    if (result == Status::SUCCESS) {
+        currentPortStatus->resize(names.size());
+        for (std::pair<string, bool> port : names) {
+            i++;
+            ALOGI("%s", port.first.c_str());
+            (*currentPortStatus)[i].portName = port.first;
+
+            PortRole currentRole;
+            currentRole.set<PortRole::powerRole>(PortPowerRole::NONE);
+            if (getCurrentRoleHelper(port.first, port.second, &currentRole) == Status::SUCCESS){
+                (*currentPortStatus)[i].currentPowerRole = currentRole.get<PortRole::powerRole>();
+            } else {
+                ALOGE("Error while retrieving portNames");
+                goto done;
+            }
+
+            currentRole.set<PortRole::dataRole>(PortDataRole::NONE);
+            if (getCurrentRoleHelper(port.first, port.second, &currentRole) == Status::SUCCESS) {
+                (*currentPortStatus)[i].currentDataRole = currentRole.get<PortRole::dataRole>();
+            } else {
+                ALOGE("Error while retrieving current port role");
+                goto done;
+            }
+
+            currentRole.set<PortRole::mode>(PortMode::NONE);
+            if (getCurrentRoleHelper(port.first, port.second, &currentRole) == Status::SUCCESS) {
+                (*currentPortStatus)[i].currentMode = currentRole.get<PortRole::mode>();
+            } else {
+                ALOGE("Error while retrieving current data role");
+                goto done;
+            }
+
+            (*currentPortStatus)[i].canChangeMode = true;
+            (*currentPortStatus)[i].canChangeDataRole =
+                port.second ? canSwitchRoleHelper(port.first) : false;
+            (*currentPortStatus)[i].canChangePowerRole =
+                port.second ? canSwitchRoleHelper(port.first) : false;
+
+            (*currentPortStatus)[i].supportedModes.push_back(PortMode::DRP);
+            (*currentPortStatus)[i].usbDataEnabled = true;
+
+            ALOGI("%d:%s connected:%d canChangeMode:%d canChagedata:%d canChangePower:%d "
+                "usbDataEnabled:%d",
+                i, port.first.c_str(), port.second,
+                (*currentPortStatus)[i].canChangeMode,
+                (*currentPortStatus)[i].canChangeDataRole,
+                (*currentPortStatus)[i].canChangePowerRole, 0);
+        }
+
+        return Status::SUCCESS;
+    }
+done:
+    return Status::ERROR;
+}
+
+void queryVersionHelper(android::hardware::usb::Usb *usb,
+                        std::vector<PortStatus> *currentPortStatus) {
+    Status status;
+    pthread_mutex_lock(&usb->mLock);
+    status = getPortStatusHelper(currentPortStatus);
+    queryMoistureDetectionStatus(currentPortStatus);
+    if (usb->mCallback != NULL) {
+        ScopedAStatus ret = usb->mCallback->notifyPortStatusChange(*currentPortStatus,
+            status);
+        if (!ret.isOk())
+            ALOGE("queryPortStatus error %s", ret.getDescription().c_str());
+    } else {
+        ALOGI("Notifying userspace skipped. Callback is NULL");
+    }
+    pthread_mutex_unlock(&usb->mLock);
+}
+
+ScopedAStatus Usb::queryPortStatus(int64_t in_transactionId) {
+    std::vector<PortStatus> currentPortStatus;
+
+    queryVersionHelper(this, &currentPortStatus);
+    pthread_mutex_lock(&mLock);
+    if (mCallback != NULL) {
+        ScopedAStatus ret = mCallback->notifyQueryPortStatus(
+            "all", Status::SUCCESS, in_transactionId);
+        if (!ret.isOk())
+            ALOGE("notifyQueryPortStatus error %s", ret.getDescription().c_str());
+    } else {
+        ALOGE("Not notifying the userspace. Callback is not set");
+    }
+    pthread_mutex_unlock(&mLock);
+
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus Usb::enableContaminantPresenceDetection(const string& in_portName,
+        bool /*in_enable*/, int64_t in_transactionId) {
+    std::vector<PortStatus> currentPortStatus;
+
+    pthread_mutex_lock(&mLock);
+    if (mCallback != NULL) {
+        ScopedAStatus ret = mCallback->notifyContaminantEnabledStatus(
+            in_portName, false, Status::ERROR, in_transactionId);
+        if (!ret.isOk())
+            ALOGE("enableContaminantPresenceDetection  error %s", ret.getDescription().c_str());
+    } else {
+        ALOGE("Not notifying the userspace. Callback is not set");
+    }
+    pthread_mutex_unlock(&mLock);
+
+    queryVersionHelper(this, &currentPortStatus);
+    return ScopedAStatus::ok();
+}
+
+
+struct data {
+    int uevent_fd;
+    ::aidl::android::hardware::usb::Usb *usb;
+};
+
+static void uevent_event(uint32_t /*epevents*/, struct data *payload) {
+    char msg[UEVENT_MSG_LEN + 2];
+    char *cp;
+    int n;
+
+    n = uevent_kernel_multicast_recv(payload->uevent_fd, msg, UEVENT_MSG_LEN);
+    if (n <= 0)
+        return;
+    if (n >= UEVENT_MSG_LEN) /* overflow -- discard */
+        return;
+
+    msg[n] = '\0';
+    msg[n + 1] = '\0';
+    cp = msg;
+
+    while (*cp) {
+        if (std::regex_match(cp, std::regex("(add)(.*)(-partner)"))) {
+            ALOGI("partner added");
+            pthread_mutex_lock(&payload->usb->mPartnerLock);
+            payload->usb->mPartnerUp = true;
+            pthread_cond_signal(&payload->usb->mPartnerCV);
+            pthread_mutex_unlock(&payload->usb->mPartnerLock);
+        } else if (!strncmp(cp, "DEVTYPE=typec_", strlen("DEVTYPE=typec_"))) {
+            std::vector<PortStatus> currentPortStatus;
+            queryVersionHelper(payload->usb, &currentPortStatus);
+
+            // Role switch is not in progress and port is in disconnected state
+            if (!pthread_mutex_trylock(&payload->usb->mRoleSwitchLock)) {
+                for (unsigned long i = 0; i < currentPortStatus.size(); i++) {
+                    DIR *dp =
+                        opendir(string(kTypecPath +
+                                       string(currentPortStatus[i].portName.c_str()) +
+                                       "-partner").c_str());
+                    if (dp == NULL) {
+                        switchToDrp(currentPortStatus[i].portName);
+                    } else {
+                        closedir(dp);
+                    }
+                }
+                pthread_mutex_unlock(&payload->usb->mRoleSwitchLock);
+            }
+            break;
+        } /* advance to after the next \0 */
+        while (*cp++) {
+        }
+    }
+}
+
+void *work(void *param) {
+    int epoll_fd, uevent_fd;
+    struct epoll_event ev;
+    int nevents = 0;
+    struct data payload;
+
+    uevent_fd = uevent_open_socket(UEVENT_MAX_EVENTS * UEVENT_MSG_LEN, true);
+
+    if (uevent_fd < 0) {
+        ALOGE("uevent_init: uevent_open_socket failed\n");
+        return NULL;
+    }
+
+    payload.uevent_fd = uevent_fd;
+    payload.usb = (::aidl::android::hardware::usb::Usb *)param;
+
+    fcntl(uevent_fd, F_SETFL, O_NONBLOCK);
+
+    ev.events = EPOLLIN;
+    ev.data.ptr = (void *)uevent_event;
+
+    epoll_fd = epoll_create(UEVENT_MAX_EVENTS);
+    if (epoll_fd == -1) {
+        ALOGE("epoll_create failed; errno=%d", errno);
+        goto error;
+    }
+
+    if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, uevent_fd, &ev) == -1) {
+        ALOGE("epoll_ctl failed; errno=%d", errno);
+        goto error;
+    }
+
+    while (!destroyThread) {
+        struct epoll_event events[UEVENT_MAX_EVENTS];
+
+        nevents = epoll_wait(epoll_fd, events, UEVENT_MAX_EVENTS, -1);
+        if (nevents == -1) {
+            if (errno == EINTR)
+                continue;
+            ALOGE("usb epoll_wait failed; errno=%d", errno);
+            break;
+        }
+
+        for (int n = 0; n < nevents; ++n) {
+            if (events[n].data.ptr)
+                (*(void (*)(int, struct data *payload))events[n].data.ptr)(events[n].events,
+                                                                           &payload);
+        }
+    }
+
+    ALOGI("exiting worker thread");
+error:
+    close(uevent_fd);
+
+    if (epoll_fd >= 0)
+        close(epoll_fd);
+
+    return NULL;
+}
+
+void sighandler(int sig) {
+    if (sig == SIGUSR1) {
+        destroyThread = true;
+        ALOGI("destroy set");
+        return;
+    }
+    signal(SIGUSR1, sighandler);
+}
+
+ScopedAStatus Usb::setCallback(
+        const shared_ptr<IUsbCallback>& in_callback) {
+
+    pthread_mutex_lock(&mLock);
+    if ((mCallback == NULL && in_callback == NULL) ||
+            (mCallback != NULL && in_callback != NULL)) {
+        mCallback = in_callback;
+        pthread_mutex_unlock(&mLock);
+        return ScopedAStatus::ok();
+    }
+
+    mCallback = in_callback;
+    ALOGI("registering callback");
+
+    if (mCallback == NULL) {
+        if  (!pthread_kill(mPoll, SIGUSR1)) {
+            pthread_join(mPoll, NULL);
+            ALOGI("pthread destroyed");
+        }
+        pthread_mutex_unlock(&mLock);
+        return ScopedAStatus::ok();
+    }
+
+    destroyThread = false;
+    signal(SIGUSR1, sighandler);
+
+    /*
+     * Create a background thread if the old callback value is NULL
+     * and being updated with a new value.
+     */
+    if (pthread_create(&mPoll, NULL, work, this)) {
+        ALOGE("pthread creation failed %d", errno);
+        mCallback = NULL;
+    }
+
+    pthread_mutex_unlock(&mLock);
+    return ScopedAStatus::ok();
+}
+
+} // namespace usb
+} // namespace hardware
+} // namespace android
+} // aidl
diff --git a/usb/aidl/default/Usb.h b/usb/aidl/default/Usb.h
new file mode 100644
index 0000000..bca86ae
--- /dev/null
+++ b/usb/aidl/default/Usb.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/file.h>
+#include <aidl/android/hardware/usb/BnUsb.h>
+#include <aidl/android/hardware/usb/BnUsbCallback.h>
+#include <utils/Log.h>
+
+#define UEVENT_MSG_LEN     2048
+#define UEVENT_MAX_EVENTS  64
+// The type-c stack waits for 4.5 - 5.5 secs before declaring a port non-pd.
+// The -partner directory would not be created until this is done.
+// Having a margin of ~3 secs for the directory and other related bookeeping
+// structures created and uvent fired.
+#define PORT_TYPE_TIMEOUT 8
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace usb {
+
+using ::aidl::android::hardware::usb::IUsbCallback;
+using ::aidl::android::hardware::usb::PortRole;
+using ::android::base::ReadFileToString;
+using ::android::base::WriteStringToFile;
+using ::android::sp;
+using ::ndk::ScopedAStatus;
+using ::std::shared_ptr;
+using ::std::string;
+
+struct Usb : public BnUsb {
+    Usb();
+
+    ScopedAStatus enableContaminantPresenceDetection(const std::string& in_portName,
+            bool in_enable, int64_t in_transactionId) override;
+    ScopedAStatus queryPortStatus(int64_t in_transactionId) override;
+    ScopedAStatus setCallback(const shared_ptr<IUsbCallback>& in_callback) override;
+    ScopedAStatus switchRole(const string& in_portName, const PortRole& in_role,
+            int64_t in_transactionId) override;
+    ScopedAStatus enableUsbData(const string& in_portName, bool in_enable,
+            int64_t in_transactionId) override;
+
+    shared_ptr<IUsbCallback> mCallback;
+    // Protects mCallback variable
+    pthread_mutex_t mLock;
+    // Protects roleSwitch operation
+    pthread_mutex_t mRoleSwitchLock;
+    // Threads waiting for the partner to come back wait here
+    pthread_cond_t mPartnerCV;
+    // lock protecting mPartnerCV
+    pthread_mutex_t mPartnerLock;
+    // Variable to signal partner coming back online after type switch
+    bool mPartnerUp;
+  private:
+    pthread_t mPoll;
+};
+
+} // namespace usb
+} // namespace hardware
+} // namespace android
+} // aidl
diff --git a/usb/aidl/default/android.hardware.usb-service.example.rc b/usb/aidl/default/android.hardware.usb-service.example.rc
new file mode 100644
index 0000000..335bca7
--- /dev/null
+++ b/usb/aidl/default/android.hardware.usb-service.example.rc
@@ -0,0 +1,4 @@
+service vendor.usb_default /vendor/bin/hw/android.hardware.usb-service.example
+    class hal
+    user system
+    group system
diff --git a/usb/aidl/default/android.hardware.usb-service.example.xml b/usb/aidl/default/android.hardware.usb-service.example.xml
new file mode 100644
index 0000000..6088194
--- /dev/null
+++ b/usb/aidl/default/android.hardware.usb-service.example.xml
@@ -0,0 +1,10 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.usb</name>
+        <version>1</version>
+        <interface>
+            <name>IUsb</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/usb/aidl/default/service.cpp b/usb/aidl/default/service.cpp
new file mode 100644
index 0000000..398458a
--- /dev/null
+++ b/usb/aidl/default/service.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+#include "Usb.h"
+
+using ::aidl::android::hardware::usb::Usb;
+
+int main() {
+    ABinderProcess_setThreadPoolMaxThreadCount(0);
+    std::shared_ptr<Usb> usb = ndk::SharedRefBase::make<Usb>();
+
+    const std::string instance = std::string() + Usb::descriptor + "/default";
+    binder_status_t status = AServiceManager_addService(usb->asBinder().get(), instance.c_str());
+    CHECK(status == STATUS_OK);
+
+    ABinderProcess_joinThreadPool();
+    return -1; // Should never be reached
+}
diff --git a/usb/aidl/vts/Android.bp b/usb/aidl/vts/Android.bp
new file mode 100644
index 0000000..00a7c93
--- /dev/null
+++ b/usb/aidl/vts/Android.bp
@@ -0,0 +1,43 @@
+//
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+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: "VtsAidlUsbTargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    srcs: ["VtsAidlUsbTargetTest.cpp"],
+    shared_libs: [
+        "libbinder_ndk",
+    ],
+    static_libs: [
+        "android.hardware.usb-V1-ndk",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
diff --git a/usb/aidl/vts/VtsAidlUsbTargetTest.cpp b/usb/aidl/vts/VtsAidlUsbTargetTest.cpp
new file mode 100644
index 0000000..09cb096
--- /dev/null
+++ b/usb/aidl/vts/VtsAidlUsbTargetTest.cpp
@@ -0,0 +1,424 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Probject
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "UsbAidlTest"
+#include <android-base/logging.h>
+
+#include <aidl/android/hardware/usb/IUsb.h>
+#include <aidl/android/hardware/usb/IUsbCallback.h>
+#include <aidl/android/hardware/usb/BnUsbCallback.h>
+#include <aidl/android/hardware/usb/PortDataRole.h>
+#include <aidl/android/hardware/usb/PortMode.h>
+#include <aidl/android/hardware/usb/PortPowerRole.h>
+#include <aidl/android/hardware/usb/PortRole.h>
+#include <aidl/android/hardware/usb/PortStatus.h>
+#include <aidl/android/hardware/usb/Status.h>
+#include <aidl/Vintf.h>
+#include <aidl/Gtest.h>
+
+#include <android/binder_auto_utils.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <gtest/gtest.h>
+
+#include <log/log.h>
+#include <stdlib.h>
+#include <chrono>
+#include <condition_variable>
+#include <mutex>
+
+#define TIMEOUT_PERIOD 10
+
+using ::aidl::android::hardware::usb::BnUsbCallback;
+using ::aidl::android::hardware::usb::IUsb;
+using ::aidl::android::hardware::usb::IUsbCallback;
+using ::aidl::android::hardware::usb::PortDataRole;
+using ::aidl::android::hardware::usb::PortMode;
+using ::aidl::android::hardware::usb::PortPowerRole;
+using ::aidl::android::hardware::usb::PortRole;
+using ::aidl::android::hardware::usb::PortStatus;
+using ::aidl::android::hardware::usb::Status;
+
+using ::ndk::ScopedAStatus;
+using ::ndk::SpAIBinder;
+using std::vector;
+using std::shared_ptr;
+using std::string;
+
+// The main test class for the USB aidl hal
+class UsbAidlTest : public testing::TestWithParam<std::string> {
+ public:
+  // Callback class for the USB aidl hal.
+  // Usb Hal will call this object upon role switch or port query.
+  class UsbCallback : public BnUsbCallback {
+    UsbAidlTest& parent_;
+    int cookie;
+
+   public:
+    UsbCallback(UsbAidlTest& parent, int cookie)
+        : parent_(parent), cookie(cookie){};
+
+    virtual ~UsbCallback() = default;
+
+    // Callback method for the port status.
+    ScopedAStatus notifyPortStatusChange(const vector<PortStatus>& currentPortStatus,
+                                         Status retval) override {
+      if (retval == Status::SUCCESS && currentPortStatus.size() > 0) {
+        parent_.usb_last_port_status.portName =
+            currentPortStatus[0].portName.c_str();
+        parent_.usb_last_port_status.currentDataRole =
+            currentPortStatus[0].currentDataRole;
+        parent_.usb_last_port_status.currentPowerRole =
+            currentPortStatus[0].currentPowerRole;
+        parent_.usb_last_port_status.currentMode =
+            currentPortStatus[0].currentMode;
+      }
+      parent_.usb_last_cookie = cookie;
+      return ScopedAStatus::ok();
+    }
+
+    // Callback method for the status of role switch operation.
+    ScopedAStatus notifyRoleSwitchStatus(const string& /*portName*/, const PortRole& newRole,
+                                         Status retval, int64_t transactionId) override {
+      parent_.usb_last_status = retval;
+      parent_.usb_last_cookie = cookie;
+      parent_.usb_last_port_role = newRole;
+      parent_.usb_role_switch_done = true;
+      parent_.last_transactionId = transactionId;
+      parent_.notify();
+      return ScopedAStatus::ok();
+    }
+
+    // Callback method for the status of enableUsbData operation
+    ScopedAStatus notifyEnableUsbDataStatus(const string& /*portName*/, bool /*enable*/,
+                                            Status /*retval*/, int64_t transactionId) override {
+      parent_.last_transactionId = transactionId;
+      parent_.usb_last_cookie = cookie;
+      parent_.enable_usb_data_done = true;
+      parent_.notify();
+      return ScopedAStatus::ok();
+    }
+
+    // Callback method for the status of enableContaminantPresenceDetection
+    ScopedAStatus notifyContaminantEnabledStatus(const string& /*portName*/, bool /*enable*/,
+                                                 Status /*retval*/, int64_t transactionId) override {
+      parent_.last_transactionId = transactionId;
+      parent_.usb_last_cookie = cookie;
+      parent_.enable_contaminant_done = true;
+      parent_.notify();
+      return ScopedAStatus::ok();
+    }
+
+    // Callback method for the status of queryPortStatus operation
+    ScopedAStatus notifyQueryPortStatus(const string& /*portName*/, Status /*retval*/,
+                                        int64_t transactionId) override {
+      parent_.last_transactionId = transactionId;
+      parent_.notify();
+      return ScopedAStatus::ok();
+    }
+  };
+
+  virtual void SetUp() override {
+    ALOGI("Setup");
+    usb = IUsb::fromBinder(
+                SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+    ASSERT_NE(usb, nullptr);
+
+    usb_cb_2 = ::ndk::SharedRefBase::make<UsbCallback>(*this, 2);
+    ASSERT_NE(usb_cb_2, nullptr);
+    const auto& ret = usb->setCallback(usb_cb_2);
+    ASSERT_TRUE(ret.isOk());
+  }
+
+  virtual void TearDown() override { ALOGI("Teardown"); }
+
+  // Used as a mechanism to inform the test about data/event callback.
+  inline void notify() {
+    std::unique_lock<std::mutex> lock(usb_mtx);
+    usb_count++;
+    usb_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(usb_mtx);
+
+    std::cv_status status = std::cv_status::no_timeout;
+    auto now = std::chrono::system_clock::now();
+    while (usb_count == 0) {
+      status =
+          usb_cv.wait_until(lock, now + std::chrono::seconds(TIMEOUT_PERIOD));
+      if (status == std::cv_status::timeout) {
+        ALOGI("timeout");
+        return status;
+      }
+    }
+    usb_count--;
+    return status;
+  }
+
+  // USB aidl hal Proxy
+  shared_ptr<IUsb> usb;
+
+  // Callback objects for usb aidl
+  // Methods of these objects are called to notify port status updates.
+  shared_ptr<IUsbCallback> usb_cb_1, usb_cb_2;
+
+  // The last conveyed status of the USB ports.
+  // Stores information of currentt_data_role, power_role for all the USB ports
+  PortStatus usb_last_port_status;
+
+  // Status of the last role switch operation.
+  Status usb_last_status;
+
+  // Port role information of the last role switch operation.
+  PortRole usb_last_port_role;
+
+  // Flag to indicate the invocation of role switch callback.
+  bool usb_role_switch_done;
+
+  // Flag to indicate the invocation of notifyContaminantEnabledStatus callback.
+  bool enable_contaminant_done;
+
+  // Flag to indicate the invocation of notifyEnableUsbDataStatus callback.
+  bool enable_usb_data_done;
+
+  // Stores the cookie of the last invoked usb callback object.
+  int usb_last_cookie;
+
+  // Last transaction ID that was recorded.
+  int64_t last_transactionId;
+  // synchronization primitives to coordinate between main test thread
+  // and the callback thread.
+  std::mutex usb_mtx;
+  std::condition_variable usb_cv;
+  int usb_count = 0;
+};
+
+/*
+ * Test to see if setCallback succeeds.
+ * Callback object is created and registered.
+ */
+TEST_P(UsbAidlTest, setCallback) {
+  ALOGI("UsbAidlTest setCallback start");
+  usb_cb_1 = ::ndk::SharedRefBase::make<UsbCallback>(*this, 1);
+  ASSERT_NE(usb_cb_1, nullptr);
+  const auto& ret = usb->setCallback(usb_cb_1);
+  ASSERT_TRUE(ret.isOk());
+  ALOGI("UsbAidlTest setCallback end");
+}
+
+/*
+ * Check to see if querying type-c
+ * port status succeeds.
+ * The callback parameters are checked to see if the transaction id
+ * matches.
+ */
+TEST_P(UsbAidlTest, queryPortStatus) {
+  ALOGI("UsbAidlTest queryPortStatus start");
+  int64_t transactionId = rand() % 10000;
+  const auto& ret = usb->queryPortStatus(transactionId);
+  ASSERT_TRUE(ret.isOk());
+  EXPECT_EQ(std::cv_status::no_timeout, wait());
+  EXPECT_EQ(2, usb_last_cookie);
+  EXPECT_EQ(transactionId, last_transactionId);
+  ALOGI("UsbAidlTest queryPortStatus end: %s", usb_last_port_status.portName.c_str());
+}
+
+/*
+ * Trying to switch a non-existent port should fail.
+ * This test case tried to switch the port with empty
+ * name which is expected to fail.
+ * The callback parameters are checked to see if the transaction id
+ * matches.
+ */
+TEST_P(UsbAidlTest, switchEmptyPort) {
+  ALOGI("UsbAidlTest switchEmptyPort start");
+  PortRole role;
+  role.set<PortRole::powerRole>(PortPowerRole::SOURCE);
+  int64_t transactionId = rand() % 10000;
+  const auto& ret = usb->switchRole("", role, transactionId);
+  ASSERT_TRUE(ret.isOk());
+  EXPECT_EQ(std::cv_status::no_timeout, wait());
+  EXPECT_EQ(Status::ERROR, usb_last_status);
+  EXPECT_EQ(transactionId, last_transactionId);
+  EXPECT_EQ(2, usb_last_cookie);
+  ALOGI("UsbAidlTest switchEmptyPort end");
+}
+
+/*
+ * Test switching the power role of usb port.
+ * Test case queries the usb ports present in device.
+ * If there is at least one usb port, a power role switch
+ * to SOURCE is attempted for the port.
+ * The callback parameters are checked to see if the transaction id
+ * matches.
+ */
+TEST_P(UsbAidlTest, switchPowerRole) {
+  ALOGI("UsbAidlTest switchPowerRole start");
+  PortRole role;
+  role.set<PortRole::powerRole>(PortPowerRole::SOURCE);
+  int64_t transactionId = rand() % 10000;
+  const auto& ret = usb->queryPortStatus(transactionId);
+  ASSERT_TRUE(ret.isOk());
+  EXPECT_EQ(std::cv_status::no_timeout, wait());
+  EXPECT_EQ(2, usb_last_cookie);
+  EXPECT_EQ(transactionId, last_transactionId);
+
+  if (!usb_last_port_status.portName.empty()) {
+    string portBeingSwitched = usb_last_port_status.portName;
+    ALOGI("switchPower role portname:%s", portBeingSwitched.c_str());
+    usb_role_switch_done = false;
+    transactionId = rand() % 10000;
+    const auto& ret = usb->switchRole(portBeingSwitched, role, transactionId);
+    ASSERT_TRUE(ret.isOk());
+
+    std::cv_status waitStatus = wait();
+    while (waitStatus == std::cv_status::no_timeout &&
+           usb_role_switch_done == false)
+      waitStatus = wait();
+
+    EXPECT_EQ(std::cv_status::no_timeout, waitStatus);
+    EXPECT_EQ(2, usb_last_cookie);
+    EXPECT_EQ(transactionId, last_transactionId);
+  }
+  ALOGI("UsbAidlTest switchPowerRole end");
+}
+
+/*
+ * Test switching the data role of usb port.
+ * Test case queries the usb ports present in device.
+ * If there is at least one usb port, a data role switch
+ * to device is attempted for the port.
+ * The callback parameters are checked to see if transaction id
+ * matches.
+ */
+TEST_P(UsbAidlTest, switchDataRole) {
+  ALOGI("UsbAidlTest switchDataRole start");
+  PortRole role;
+  role.set<PortRole::dataRole>(PortDataRole::DEVICE);
+  int64_t transactionId = rand() % 10000;
+  const auto& ret = usb->queryPortStatus(transactionId);
+  ASSERT_TRUE(ret.isOk());
+  EXPECT_EQ(std::cv_status::no_timeout, wait());
+  EXPECT_EQ(2, usb_last_cookie);
+  EXPECT_EQ(transactionId, last_transactionId);
+
+  if (!usb_last_port_status.portName.empty()) {
+    string portBeingSwitched = usb_last_port_status.portName;
+    ALOGI("portname:%s", portBeingSwitched.c_str());
+    usb_role_switch_done = false;
+    transactionId = rand() % 10000;
+    const auto& ret = usb->switchRole(portBeingSwitched, role, transactionId);
+    ASSERT_TRUE(ret.isOk());
+
+    std::cv_status waitStatus = wait();
+    while (waitStatus == std::cv_status::no_timeout &&
+           usb_role_switch_done == false)
+      waitStatus = wait();
+
+    EXPECT_EQ(std::cv_status::no_timeout, waitStatus);
+    EXPECT_EQ(2, usb_last_cookie);
+    EXPECT_EQ(transactionId, last_transactionId);
+  }
+  ALOGI("UsbAidlTest switchDataRole end");
+}
+
+/*
+ * Test enabling contaminant presence detection of the port.
+ * Test case queries the usb ports present in device.
+ * If there is at least one usb port, enabling contaminant detection
+ * is attempted for the port.
+ * The callback parameters are checked to see if transaction id
+ * matches.
+ */
+TEST_P(UsbAidlTest, enableContaminantPresenceDetection) {
+  ALOGI("UsbAidlTest enableContaminantPresenceDetection start");
+  int64_t transactionId = rand() % 10000;
+  const auto& ret = usb->queryPortStatus(transactionId);
+  ASSERT_TRUE(ret.isOk());
+  EXPECT_EQ(std::cv_status::no_timeout, wait());
+  EXPECT_EQ(2, usb_last_cookie);
+  EXPECT_EQ(transactionId, last_transactionId);
+
+  if (!usb_last_port_status.portName.empty()) {
+    ALOGI("portname:%s", usb_last_port_status.portName.c_str());
+    enable_contaminant_done = false;
+    transactionId = rand() % 10000;
+    const auto& ret = usb->enableContaminantPresenceDetection(usb_last_port_status.portName,
+                                                              true, transactionId);
+    ASSERT_TRUE(ret.isOk());
+
+    std::cv_status waitStatus = wait();
+    while (waitStatus == std::cv_status::no_timeout &&
+           enable_contaminant_done == false)
+      waitStatus = wait();
+
+    EXPECT_EQ(std::cv_status::no_timeout, waitStatus);
+    EXPECT_EQ(2, usb_last_cookie);
+    EXPECT_EQ(transactionId, last_transactionId);
+  }
+  ALOGI("UsbAidlTest enableContaminantPresenceDetection end");
+}
+
+/*
+ * Test enabling Usb data of the port.
+ * Test case queries the usb ports present in device.
+ * If there is at least one usb port, enabling Usb data is attempted
+ * for the port.
+ * The callback parameters are checked to see if transaction id
+ * matches.
+ */
+TEST_P(UsbAidlTest, enableUsbData) {
+  ALOGI("UsbAidlTest enableUsbData start");
+  int64_t transactionId = rand() % 10000;
+  const auto& ret = usb->queryPortStatus(transactionId);
+  ASSERT_TRUE(ret.isOk());
+  EXPECT_EQ(std::cv_status::no_timeout, wait());
+  EXPECT_EQ(2, usb_last_cookie);
+  EXPECT_EQ(transactionId, last_transactionId);
+
+  if (!usb_last_port_status.portName.empty()) {
+    ALOGI("portname:%s", usb_last_port_status.portName.c_str());
+    enable_usb_data_done = false;
+    transactionId = rand() % 10000;
+    const auto& ret = usb->enableUsbData(usb_last_port_status.portName, true, transactionId);
+    ASSERT_TRUE(ret.isOk());
+
+    std::cv_status waitStatus = wait();
+    while (waitStatus == std::cv_status::no_timeout &&
+           enable_usb_data_done == false)
+      waitStatus = wait();
+
+    EXPECT_EQ(std::cv_status::no_timeout, waitStatus);
+    EXPECT_EQ(2, usb_last_cookie);
+    EXPECT_EQ(transactionId, last_transactionId);
+  }
+  ALOGI("UsbAidlTest enableUsbData end");
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(UsbAidlTest);
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, UsbAidlTest,
+        testing::ValuesIn(::android::getAidlHalInstanceNames(IUsb::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/usb/gadget/1.1/default/lib/UsbGadgetUtils.cpp b/usb/gadget/1.1/default/lib/UsbGadgetUtils.cpp
index 8402853..4c40bf8 100644
--- a/usb/gadget/1.1/default/lib/UsbGadgetUtils.cpp
+++ b/usb/gadget/1.1/default/lib/UsbGadgetUtils.cpp
@@ -178,6 +178,9 @@
 
 Status addAdb(MonitorFfs* monitorFfs, int* functionCount) {
     ALOGI("setCurrentUsbFunctions Adb");
+    if (!WriteStringToFile("1", DESC_USE_PATH))
+        return Status::ERROR;
+
     if (!monitorFfs->addInotifyFd("/dev/usb-ffs/adb/")) return Status::ERROR;
 
     if (linkFunction("ffs.adb", (*functionCount)++)) return Status::ERROR;
diff --git a/usb/gadget/1.2/default/lib/UsbGadgetUtils.cpp b/usb/gadget/1.2/default/lib/UsbGadgetUtils.cpp
index 8986556..fa50821 100644
--- a/usb/gadget/1.2/default/lib/UsbGadgetUtils.cpp
+++ b/usb/gadget/1.2/default/lib/UsbGadgetUtils.cpp
@@ -190,6 +190,9 @@
 
 Status addAdb(MonitorFfs* monitorFfs, int* functionCount) {
     ALOGI("setCurrentUsbFunctions Adb");
+    if (!WriteStringToFile("1", DESC_USE_PATH))
+        return Status::ERROR;
+
     if (!monitorFfs->addInotifyFd("/dev/usb-ffs/adb/")) return Status::ERROR;
 
     if (linkFunction("ffs.adb", (*functionCount)++)) return Status::ERROR;
diff --git a/vibrator/1.0/vts/OWNERS b/vibrator/1.0/vts/OWNERS
new file mode 100644
index 0000000..75b9a4b
--- /dev/null
+++ b/vibrator/1.0/vts/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 345036
+michaelwr@google.com
+leungv@google.com
diff --git a/vibrator/1.1/vts/OWNERS b/vibrator/1.1/vts/OWNERS
new file mode 100644
index 0000000..44bfe56
--- /dev/null
+++ b/vibrator/1.1/vts/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 345036
+include ../../1.0/vts/OWNERS
diff --git a/vibrator/1.2/vts/OWNERS b/vibrator/1.2/vts/OWNERS
new file mode 100644
index 0000000..44bfe56
--- /dev/null
+++ b/vibrator/1.2/vts/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 345036
+include ../../1.0/vts/OWNERS
diff --git a/vibrator/1.3/vts/OWNERS b/vibrator/1.3/vts/OWNERS
new file mode 100644
index 0000000..44bfe56
--- /dev/null
+++ b/vibrator/1.3/vts/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 345036
+include ../../1.0/vts/OWNERS
diff --git a/vibrator/aidl/Android.bp b/vibrator/aidl/Android.bp
index 22219b0..d4d5857 100644
--- a/vibrator/aidl/Android.bp
+++ b/vibrator/aidl/Android.bp
@@ -10,6 +10,7 @@
 aidl_interface {
     name: "android.hardware.vibrator",
     vendor_available: true,
+    host_supported: true,
     srcs: [
         "android/hardware/vibrator/*.aidl",
     ],
diff --git a/vibrator/aidl/OWNERS b/vibrator/aidl/OWNERS
index 4bd5614..3982c7b 100644
--- a/vibrator/aidl/OWNERS
+++ b/vibrator/aidl/OWNERS
@@ -1,4 +1,4 @@
+# Bug component: 345036
+include platform/frameworks/base:/services/core/java/com/android/server/vibrator/OWNERS
 chasewu@google.com
-leungv@google.com
-lsandrade@google.com
-michaelwr@google.com
+taikuo@google.com
diff --git a/vibrator/aidl/android/hardware/vibrator/ActivePwle.aidl b/vibrator/aidl/android/hardware/vibrator/ActivePwle.aidl
index fd5f8d1..6757476 100644
--- a/vibrator/aidl/android/hardware/vibrator/ActivePwle.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/ActivePwle.aidl
@@ -22,26 +22,50 @@
      * Amplitude ranging from 0.0 (inclusive) to 1.0 (inclusive)
      * in units of output acceleration amplitude, not voltage amplitude.
      *
+     * Values should fall within the range of 0.0 (inclusive) to the maximum defined
+     * by the corresponding entries in IVibrator#getBandwidthAmplitudeMap (inclusive).
+     * If startFrequency falls between two entries, the value will not exceed the
+     * largest amplitude of the two bounding frequencies.
+     *
      * 0.0 represents no output acceleration amplitude
-     * 1.0 represents maximum output acceleration amplitude at resonant frequency
+     * 1.0 represents maximum output acceleration amplitude
+     *     across all supported frequencies
      */
     float startAmplitude;
+
     /**
      * Absolute frequency point in the units of hertz
+     *
+     * Values are within the continuous inclusive frequency range defined by
+     * IVibrator#getBandwidthAmplitudeMap, and not limited by the
+     * IVibrator#getFrequencyResolution.
      */
     float startFrequency;
+
     /**
      * Amplitude ranging from 0.0 (inclusive) to 1.0 (inclusive)
      * in units of output acceleration amplitude, not voltage amplitude.
      *
+     * Values should fall within the range of 0.0 (inclusive) to the maximum defined
+     * by the corresponding entries in IVibrator#getBandwidthAmplitudeMap (inclusive).
+     * If endFrequency falls between two entries, the value will not exceed the
+     * largest amplitude of the two bounding frequencies.
+     *
      * 0.0 represents no output acceleration amplitude
-     * 1.0 represents maximum output acceleration amplitude at resonant frequency
+     * 1.0 represents maximum output acceleration amplitude
+     *     across all supported frequencies
      */
     float endAmplitude;
+
     /**
      * Absolute frequency point in the units of hertz
+     *
+     * Values are within the continuous inclusive frequency range defined by
+     * IVibrator#getBandwidthAmplitudeMap, and not limited by the
+     * IVibrator#getFrequencyResolution.
      */
     float endFrequency;
+
     /**
      * Total duration from start point to end point in the units of milliseconds
      */
diff --git a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
index 592d151..b4e7e44 100644
--- a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
@@ -305,6 +305,10 @@
      * of getFrequencyResolution(). The value returned by getResonantFrequency() must be
      * represented in the returned list.
      *
+     * The amplitude values represent the maximum output acceleration amplitude supported for each
+     * given frequency. Equal amplitude values for different frequencies represent equal output
+     * accelerations.
+     *
      * @return The maximum output acceleration amplitude for each supported frequency,
      *         starting at getMinimumFrequency()
      */
diff --git a/vibrator/aidl/default/Android.bp b/vibrator/aidl/default/Android.bp
index d463f51..c4140be 100644
--- a/vibrator/aidl/default/Android.bp
+++ b/vibrator/aidl/default/Android.bp
@@ -9,11 +9,12 @@
 
 cc_library_static {
     name: "libvibratorexampleimpl",
-    vendor: true,
+    vendor_available: true,
+    host_supported: true,
     shared_libs: [
         "libbase",
         "libbinder_ndk",
-        "android.hardware.vibrator-V2-ndk_platform",
+        "android.hardware.vibrator-V2-ndk",
     ],
     export_include_dirs: ["include"],
     srcs: [
@@ -24,21 +25,69 @@
         ":__subpackages__",
         "//hardware/interfaces/tests/extension/vibrator:__subpackages__",
     ],
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
+}
+
+filegroup {
+    name: "android.hardware.vibrator.xml",
+    srcs: ["android.hardware.vibrator.xml"],
 }
 
 cc_binary {
     name: "android.hardware.vibrator-service.example",
     relative_install_path: "hw",
     init_rc: ["vibrator-default.rc"],
-    vintf_fragments: ["vibrator-default.xml"],
+    vintf_fragments: [":android.hardware.vibrator.xml"],
     vendor: true,
     shared_libs: [
         "libbase",
         "libbinder_ndk",
-        "android.hardware.vibrator-V2-ndk_platform",
+        "android.hardware.vibrator-V2-ndk",
     ],
     static_libs: [
         "libvibratorexampleimpl",
     ],
     srcs: ["main.cpp"],
 }
+
+cc_fuzz {
+    name: "android.hardware.vibrator-service.example_fuzzer",
+    host_supported: true,
+    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: [
+            "smoreland@google.com",
+        ],
+    },
+}
diff --git a/vibrator/aidl/default/Vibrator.cpp b/vibrator/aidl/default/Vibrator.cpp
index 5755ce5..ddc6ee0 100644
--- a/vibrator/aidl/default/Vibrator.cpp
+++ b/vibrator/aidl/default/Vibrator.cpp
@@ -24,21 +24,23 @@
 namespace hardware {
 namespace vibrator {
 
-static constexpr int32_t kComposeDelayMaxMs = 1000;
-static constexpr int32_t kComposeSizeMax = 256;
-static constexpr int32_t kComposePwleSizeMax = 127;
+static constexpr int32_t COMPOSE_DELAY_MAX_MS = 1000;
+static constexpr int32_t COMPOSE_SIZE_MAX = 256;
+static constexpr int32_t COMPOSE_PWLE_SIZE_MAX = 127;
 
-static constexpr float kResonantFrequency = 150.0;
-static constexpr float kQFactor = 11.0;
+static constexpr float Q_FACTOR = 11.0;
 static constexpr int32_t COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS = 16383;
 static constexpr float PWLE_LEVEL_MIN = 0.0;
-static constexpr float PWLE_LEVEL_MAX = 0.98256;
+static constexpr float PWLE_LEVEL_MAX = 1.0;
 static constexpr float PWLE_FREQUENCY_RESOLUTION_HZ = 1.0;
 static constexpr float PWLE_FREQUENCY_MIN_HZ = 140.0;
+static constexpr float RESONANT_FREQUENCY_HZ = 150.0;
 static constexpr float PWLE_FREQUENCY_MAX_HZ = 160.0;
+static constexpr float PWLE_BW_MAP_SIZE =
+        1 + ((PWLE_FREQUENCY_MAX_HZ - PWLE_FREQUENCY_MIN_HZ) / PWLE_FREQUENCY_RESOLUTION_HZ);
 
 ndk::ScopedAStatus Vibrator::getCapabilities(int32_t* _aidl_return) {
-    LOG(INFO) << "Vibrator reporting capabilities";
+    LOG(VERBOSE) << "Vibrator reporting capabilities";
     *_aidl_return = IVibrator::CAP_ON_CALLBACK | IVibrator::CAP_PERFORM_CALLBACK |
                     IVibrator::CAP_AMPLITUDE_CONTROL | IVibrator::CAP_EXTERNAL_CONTROL |
                     IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL | IVibrator::CAP_COMPOSE_EFFECTS |
@@ -49,18 +51,18 @@
 }
 
 ndk::ScopedAStatus Vibrator::off() {
-    LOG(INFO) << "Vibrator off";
+    LOG(VERBOSE) << "Vibrator off";
     return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus Vibrator::on(int32_t timeoutMs,
                                 const std::shared_ptr<IVibratorCallback>& callback) {
-    LOG(INFO) << "Vibrator on for timeoutMs: " << timeoutMs;
+    LOG(VERBOSE) << "Vibrator on for timeoutMs: " << timeoutMs;
     if (callback != nullptr) {
         std::thread([=] {
-            LOG(INFO) << "Starting on on another thread";
+            LOG(VERBOSE) << "Starting on on another thread";
             usleep(timeoutMs * 1000);
-            LOG(INFO) << "Notifying on complete";
+            LOG(VERBOSE) << "Notifying on complete";
             if (!callback->onComplete().isOk()) {
                 LOG(ERROR) << "Failed to call onComplete";
             }
@@ -72,7 +74,7 @@
 ndk::ScopedAStatus Vibrator::perform(Effect effect, EffectStrength strength,
                                      const std::shared_ptr<IVibratorCallback>& callback,
                                      int32_t* _aidl_return) {
-    LOG(INFO) << "Vibrator perform";
+    LOG(VERBOSE) << "Vibrator perform";
 
     if (effect != Effect::CLICK && effect != Effect::TICK) {
         return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
@@ -86,9 +88,9 @@
 
     if (callback != nullptr) {
         std::thread([=] {
-            LOG(INFO) << "Starting perform on another thread";
+            LOG(VERBOSE) << "Starting perform on another thread";
             usleep(kEffectMillis * 1000);
-            LOG(INFO) << "Notifying perform complete";
+            LOG(VERBOSE) << "Notifying perform complete";
             callback->onComplete();
         }).detach();
     }
@@ -103,7 +105,7 @@
 }
 
 ndk::ScopedAStatus Vibrator::setAmplitude(float amplitude) {
-    LOG(INFO) << "Vibrator set amplitude: " << amplitude;
+    LOG(VERBOSE) << "Vibrator set amplitude: " << amplitude;
     if (amplitude <= 0.0f || amplitude > 1.0f) {
         return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_ILLEGAL_ARGUMENT));
     }
@@ -111,17 +113,17 @@
 }
 
 ndk::ScopedAStatus Vibrator::setExternalControl(bool enabled) {
-    LOG(INFO) << "Vibrator set external control: " << enabled;
+    LOG(VERBOSE) << "Vibrator set external control: " << enabled;
     return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus Vibrator::getCompositionDelayMax(int32_t* maxDelayMs) {
-    *maxDelayMs = kComposeDelayMaxMs;
+    *maxDelayMs = COMPOSE_DELAY_MAX_MS;
     return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus Vibrator::getCompositionSizeMax(int32_t* maxSize) {
-    *maxSize = kComposeSizeMax;
+    *maxSize = COMPOSE_SIZE_MAX;
     return ndk::ScopedAStatus::ok();
 }
 
@@ -153,7 +155,7 @@
 
 ndk::ScopedAStatus Vibrator::compose(const std::vector<CompositeEffect>& composite,
                                      const std::shared_ptr<IVibratorCallback>& callback) {
-    if (composite.size() > kComposeSizeMax) {
+    if (composite.size() > COMPOSE_SIZE_MAX) {
         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
     }
 
@@ -161,7 +163,7 @@
     getSupportedPrimitives(&supported);
 
     for (auto& e : composite) {
-        if (e.delayMs > kComposeDelayMaxMs) {
+        if (e.delayMs > COMPOSE_DELAY_MAX_MS) {
             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
         }
         if (e.scale < 0.0f || e.scale > 1.0f) {
@@ -173,14 +175,14 @@
     }
 
     std::thread([=] {
-        LOG(INFO) << "Starting compose on another thread";
+        LOG(VERBOSE) << "Starting compose on another thread";
 
         for (auto& e : composite) {
             if (e.delayMs) {
                 usleep(e.delayMs * 1000);
             }
-            LOG(INFO) << "triggering primitive " << static_cast<int>(e.primitive) << " @ scale "
-                      << e.scale;
+            LOG(VERBOSE) << "triggering primitive " << static_cast<int>(e.primitive) << " @ scale "
+                         << e.scale;
 
             int32_t durationMs;
             getPrimitiveDuration(e.primitive, &durationMs);
@@ -188,7 +190,7 @@
         }
 
         if (callback != nullptr) {
-            LOG(INFO) << "Notifying perform complete";
+            LOG(VERBOSE) << "Notifying perform complete";
             callback->onComplete();
         }
     }).detach();
@@ -207,24 +209,24 @@
     if (std::find(effects.begin(), effects.end(), effect) == effects.end()) {
         return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
     } else {
-        LOG(INFO) << "Enabling always-on ID " << id << " with " << toString(effect) << "/"
-                  << toString(strength);
+        LOG(VERBOSE) << "Enabling always-on ID " << id << " with " << toString(effect) << "/"
+                     << toString(strength);
         return ndk::ScopedAStatus::ok();
     }
 }
 
 ndk::ScopedAStatus Vibrator::alwaysOnDisable(int32_t id) {
-    LOG(INFO) << "Disabling always-on ID " << id;
+    LOG(VERBOSE) << "Disabling always-on ID " << id;
     return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus Vibrator::getResonantFrequency(float *resonantFreqHz) {
-    *resonantFreqHz = kResonantFrequency;
+    *resonantFreqHz = RESONANT_FREQUENCY_HZ;
     return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus Vibrator::getQFactor(float *qFactor) {
-    *qFactor = kQFactor;
+    *qFactor = Q_FACTOR;
     return ndk::ScopedAStatus::ok();
 }
 
@@ -239,11 +241,26 @@
 }
 
 ndk::ScopedAStatus Vibrator::getBandwidthAmplitudeMap(std::vector<float> *_aidl_return) {
-    // A valid array should be of size:
-    //     (PWLE_FREQUENCY_MAX_HZ - PWLE_FREQUENCY_MIN_HZ) / PWLE_FREQUENCY_RESOLUTION_HZ
-    *_aidl_return = {0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.10,
-                     0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.20};
-    return ndk::ScopedAStatus::ok();
+    // The output BandwidthAmplitudeMap will be as below and the maximum
+    // amplitude 1.0 will be set on RESONANT_FREQUENCY_HZ
+    // {0.9, 0.91, 0.92, 0.93, 0.94, 0.95, 0.96, 0.97, 0.98, 0.99, 1, 0.99, 0.98, 0.97,
+    // 0.96, 0.95, 0.94, 0.93, 0.92, 0.91, 0.9}
+    int32_t capabilities = 0;
+    int halfMapSize = PWLE_BW_MAP_SIZE / 2;
+    Vibrator::getCapabilities(&capabilities);
+    if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
+        std::vector<float> bandwidthAmplitudeMap(PWLE_BW_MAP_SIZE, PWLE_LEVEL_MAX);
+        for (int i = 0; i < halfMapSize; ++i) {
+            bandwidthAmplitudeMap[halfMapSize + i + 1] =
+                    bandwidthAmplitudeMap[halfMapSize + i] - 0.01;
+            bandwidthAmplitudeMap[halfMapSize - i - 1] =
+                    bandwidthAmplitudeMap[halfMapSize - i] - 0.01;
+        }
+        *_aidl_return = bandwidthAmplitudeMap;
+        return ndk::ScopedAStatus::ok();
+    } else {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+    }
 }
 
 ndk::ScopedAStatus Vibrator::getPwlePrimitiveDurationMax(int32_t *durationMs) {
@@ -252,7 +269,7 @@
 }
 
 ndk::ScopedAStatus Vibrator::getPwleCompositionSizeMax(int32_t *maxSize) {
-    *maxSize = kComposePwleSizeMax;
+    *maxSize = COMPOSE_PWLE_SIZE_MAX;
     return ndk::ScopedAStatus::ok();
 }
 
@@ -380,10 +397,10 @@
     }
 
     std::thread([=] {
-        LOG(INFO) << "Starting composePwle on another thread";
+        LOG(VERBOSE) << "Starting composePwle on another thread";
         usleep(totalDuration * 1000);
         if (callback != nullptr) {
-            LOG(INFO) << "Notifying compose PWLE complete";
+            LOG(VERBOSE) << "Notifying compose PWLE complete";
             callback->onComplete();
         }
     }).detach();
diff --git a/vibrator/aidl/default/vibrator-default.xml b/vibrator/aidl/default/android.hardware.vibrator.xml
similarity index 100%
rename from vibrator/aidl/default/vibrator-default.xml
rename to vibrator/aidl/default/android.hardware.vibrator.xml
diff --git a/vibrator/aidl/default/apex/Android.bp b/vibrator/aidl/default/apex/Android.bp
new file mode 100644
index 0000000..7949057
--- /dev/null
+++ b/vibrator/aidl/default/apex/Android.bp
@@ -0,0 +1,41 @@
+package {
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+apex_key {
+    name: "com.android.hardware.vibrator.key",
+    public_key: "com.android.hardware.vibrator.avbpubkey",
+    private_key: "com.android.hardware.vibrator.pem",
+}
+
+android_app_certificate {
+    name: "com.android.hardware.vibrator.certificate",
+    certificate: "com.android.hardware.vibrator",
+}
+
+prebuilt_etc {
+    name: "com.android.hardware.vibrator.rc",
+    src: "com.android.hardware.vibrator.rc",
+    installable: false,
+}
+
+apex {
+    name: "com.android.hardware.vibrator",
+    manifest: "apex_manifest.json",
+    key: "com.android.hardware.vibrator.key",
+    certificate: ":com.android.hardware.vibrator.certificate",
+    file_contexts: "file_contexts",
+    use_vndk_as_stable: true,
+    updatable: false,
+    // Install the apex in /vendor/apex
+    soc_specific: true,
+    binaries: [
+        "android.hardware.vibrator-service.example",
+    ],
+    prebuilts: [
+        "com.android.hardware.vibrator.rc",
+    ],
+    vintf_fragments: [":android.hardware.vibrator.xml"],
+    // vibrator.default.so is not needed by the AIDL service binary.
+    overrides: ["vibrator.default"],
+}
diff --git a/vibrator/aidl/default/apex/apex_manifest.json b/vibrator/aidl/default/apex/apex_manifest.json
new file mode 100644
index 0000000..3f395c0
--- /dev/null
+++ b/vibrator/aidl/default/apex/apex_manifest.json
@@ -0,0 +1,4 @@
+{
+  "name": "com.android.hardware.vibrator",
+  "version": 1
+}
diff --git a/vibrator/aidl/default/apex/com.android.hardware.vibrator.avbpubkey b/vibrator/aidl/default/apex/com.android.hardware.vibrator.avbpubkey
new file mode 100644
index 0000000..a6ca630
--- /dev/null
+++ b/vibrator/aidl/default/apex/com.android.hardware.vibrator.avbpubkey
Binary files differ
diff --git a/vibrator/aidl/default/apex/com.android.hardware.vibrator.pem b/vibrator/aidl/default/apex/com.android.hardware.vibrator.pem
new file mode 100644
index 0000000..c0f5c50
--- /dev/null
+++ b/vibrator/aidl/default/apex/com.android.hardware.vibrator.pem
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIJKAIBAAKCAgEAnIEo7HGpVc62cFPmwT3MOiHQANHVbawHpbp//x3xK7acK6So
+rUu8XJnsO0kAA/Vwtfqqo5GgmBVUr4ahW+MJ/W/X7NP5hAetQWQcGFc0Yhqmoi1g
+vTDRon2i6+mhfUFJqqy8t3vLFehqgkQCe8gGiEVl43+PODtfIae+AaPbTl8R9ErQ
+l3ESBfRElkMQo2beC7e8k5joLEA3q85Q7rdSFUdhoUSXMVRHmBVJxezYI/3SLFtj
+7ULKaGtOgUFlj5R9akr9y8+sG9NBJI5HJZgqz46l+ZuNkdkPlDK6arD5eL9lkpxt
+GeXhtwBPdgZIuSTe/tFeYU65MmwLxVnStDJ67k3AFKC0Zg7ISVemCRofSOEhyUm3
+DoB1G9UiBj3pNmhwPNYiohW3pFZuLgBArAT8nTi4txmCBMNStz7kNVW8sv8nlBEz
+D+nOuoB8tGAF7+fsaBKVQI6yJd2tgkpRM5E8NNrLYL+ignRztzfHjNDtw5Xn4QHA
+Ds1GrNqq25uBxvrH5cDa2HFvZryuejlzvGp6YAkPUwZrYJ/ij7i+98EvXowgED/7
+gFnXmkkyW1LQ0BUxJtKKEjnSno8leGbcospSUDt8uiBF7Vnn3atokRpl6rr2k0qa
+5ELx+vrQT+LUUo0MuZkAW9qKfYLBF8UOCiK1Ytvs9bxK3Jb93E+lJAe/HQkCAwEA
+AQKCAgADnZA+dhm9W7snOSj5id3v8dwGSNKvZ+v9TiOq1xw9MEjHUVR8PGWrlfq5
+G+SeMstZyOKsSK73FHcSXv/XSZVvf2fzlqoK/Mpp2lAz17/kDE2RLY8wj7IoGNLs
+tEcAx8NV6AusCXYVmXrsa3nLNkHAYCoMaWP7npOCCYgALbLhSpz1kczj0r7h2FTF
+S+NUgwnaJ3J5zmx+qTUgCPIhsaZ5y15cBWOgxhupTcSYh/IuUqzKTYovbv2SD/iO
+T95yxLFpBTZ7wN5u/iBhIdBO9Ab5KIh5Dbjlh6guekWINXJt8a39BxQWJxNh0OYF
+CfwgGtPz+w49HT52Bbz34C1X8FqaoXxJUHaJ7e83Y/1qzENNPOsmdscMuzrjlVox
+gyQPIS5HzASD2NktnShwE2QUMhZcovkPIhFxos7JDMvOTXf6LVMXKWGa4HZqb4Z2
+dBp/bZzuV+OOHXq9emCkRwO5aor2qfefSf+xcycDWzaWTJfvnEXulFXYtqiGOEL7
+hyvr38Tll6dOLO8KkwvHaf51wZl/jCTo+7akdpokUh0Klg3/KKRiaScHQotkrVuD
+MGL+kWSZqZ6sZKs8z3xh4oj2d6P1qHEeu85+DY/GyHJ2Ek4athcT0jmqb4A/0Tq9
+1zr5IXo+ps20YjW5bFvXbvKVZYggsJyacw6WhTFD9eN8fn+UoQKCAQEAzwrs/QWv
+yWoWLOaF39bL6JSdq8juynswdb2NjcHV/b7dzhgf0aDnA6WtJcHlfRcnA8haeoEQ
+n0qzPAirexz2AtWfJm41gYTqWTwaaNkbwxGMMvLV/IQebk3pHdAdONFYpLloJvlt
+4ys8W1gdMKwzSRvR4VPYwIfIqb/vYxZhme0JBF0X5iPFkID9Q1cJeaRx9PhCvX4o
+LBb6impUkeTIhxbGgbuudGyhcyvKrPdcx1ts69r6NOme2hvBhrbZGVaUEtlHvEu0
+1JvNvPJyK2XvHI3EtERzjUPm3s+Gh5REvdXXaz1GC4HUSFZkOG8/HgSZoEYVkSJH
+QoCnfXc4VG4jrQKCAQEAwYL4KvpltG85DNoYava71adQfYwitQah8omGU+dqWjjQ
+m8WLKo1cjEO6tfIp7UFSz4mJvwhxj9aqdwu2RyGoeZHKOhxluZIH9mcoPggL7Kgj
+xEJfkwy5zbReujM71n5FOhR2zOltXXa5YrN9983fZeZK8FRchEBDwyUf73dkwRri
+uvyY793OIqYjuJXO/9dtSyK1jEmDUTLoquM610RLLK4j8hXQ9C/sMlDfHzlUzXff
+ZsvWL5U4D3e6cL55cP7lr8cYR1z+AcZsjd7eNlNXO1v4o50B7bOayr7/zsTlfXss
+ZoP7yJcYeXEpcIx5KPS44CAaDeZfQkOFcz7DzFQqTQKCAQEAx2aQZAdsC6GehdPm
+r3PhorgvOlkkkeIfA+ZxREug2udOG8VkL7K1iu+vWKPrb5QywRPfAAj5h1CcWn9H
+GCUGUiiHRK3z3i+yvAqErOIcOLzXt+HkcXSVEkr67vmWizgkFVFzm8WyLY1gbeDp
+DA1sv0aJ1me4Y4Tin4n49geCLIr7mjZGZCGjjs6MHKTgvUTBc9r9/B5adkwTM+fA
+V1puPpySxjOJixtsSs2sPvVlZ6MHvgeB3h/6G7mLo0DKyfp2Vcjpq9GF8RW1Cfq+
+NknQBkILZkpet3jkC0b3G/CSW/ptpBy5Ly/00U5S639I3JI1mwSklMjctJHPvahq
+mfYRaQKCAQAnMzzKmAbaUl2gON4RbQIH+ejYRfcR7NIJq8pGXO6ycCfyJkZWzGQf
+FelQykmsAjugRyBcTn2Swc2uZ/T429yhI+NveikxOl/ajnMcfczMmBMGwttRkpZh
+EVTPK2nHvbSQW2zlfbPl5xMO54VxGYdTwR8VKEHFmK8hbPfXLrx+Uc/0SQ9CKBCF
+/FnoHpDcSuuc+N8GGC492K5BT96vlOoVlwE5HSpDDSIv3yoTzS1cohfjXw94fCXr
+HDnsdOls9nXY8d/9NN1Pxr5ezvL81k0pfSwVGM03Ndb5k0+Gt2Q10ynfaoUq0VDn
+6QCYCBzTKx/4ZwhgIHbTmZIDEoffcH1RAoIBACIpqVGAa2/t3c0BCN7PLPGIsC/w
+5YwxqVNUM0FK220RoO0vbSEGvba8NJyBKSaokgPwhmNlmVE+r17B78oLfP8GFtAx
+Jz52WkjVULNb07WSIHCUxeoNZf9qEANdvfMwW4effjkrmxEtVLHdGC72Lg+am30s
+QaJqLmKsRZeE6Js2+ZXeRKoXN8wLLGp/CDVnDdLUEK6SdsujI4jXEq3DT+9eGh6X
+mXl7vWFzbPrAGcHM4Ad8uY2BHznCGxvJn4E4u+EH+l4OX334Q4gM+gOIRt0xkHVG
+9OXFRrjPVCWZCH1dOdkC5DomKCgyKBHLObtBv3dHXXDtEbeZ8fGbJFuoBhA=
+-----END RSA PRIVATE KEY-----
diff --git a/vibrator/aidl/default/apex/com.android.hardware.vibrator.pk8 b/vibrator/aidl/default/apex/com.android.hardware.vibrator.pk8
new file mode 100644
index 0000000..d20cc33
--- /dev/null
+++ b/vibrator/aidl/default/apex/com.android.hardware.vibrator.pk8
Binary files differ
diff --git a/vibrator/aidl/default/apex/com.android.hardware.vibrator.rc b/vibrator/aidl/default/apex/com.android.hardware.vibrator.rc
new file mode 100644
index 0000000..42615ad
--- /dev/null
+++ b/vibrator/aidl/default/apex/com.android.hardware.vibrator.rc
@@ -0,0 +1,4 @@
+service vendor.vibrator-default /apex/com.android.hardware.vibrator/bin/hw/android.hardware.vibrator-service.example
+    class hal
+    user nobody
+    group nobody
diff --git a/vibrator/aidl/default/apex/com.android.hardware.vibrator.x509.pem b/vibrator/aidl/default/apex/com.android.hardware.vibrator.x509.pem
new file mode 100644
index 0000000..993245b
--- /dev/null
+++ b/vibrator/aidl/default/apex/com.android.hardware.vibrator.x509.pem
@@ -0,0 +1,34 @@
+-----BEGIN CERTIFICATE-----
+MIIF3zCCA8cCFBJmLB9vGtl8nENMVa8g51Y2vRhPMA0GCSqGSIb3DQEBCwUAMIGq
+MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
+bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEi
+MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTEmMCQGA1UEAwwdY29t
+LmFuZHJvaWQuaGFyZHdhcmUudmlicmF0b3IwIBcNMjEwOTE2MTcyOTA5WhgPNDc1
+OTA4MTMxNzI5MDlaMIGqMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5p
+YTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4G
+A1UECwwHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNv
+bTEmMCQGA1UEAwwdY29tLmFuZHJvaWQuaGFyZHdhcmUudmlicmF0b3IwggIiMA0G
+CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDV857uzUSXWQNWIuiNRwt1zd/eSB8P
+iVNq0qTexlZvamXr6h5VwX45iJeDVCxlx3uktXXP2NH7U01A5gl8Hix6iodNe3sJ
+fFIhzUiqdMfAn+6RWcJcb3v6J58D6R+htgtaSgv8WOLkIZyhbmU3NToc7dNe2j0U
+wh6xfYhpj/s0RManSTZW19C2H8g5eNfhEZgDT+KOUIgepv/x6Y5IR147JPh8Ha7g
+vxM87ceErSvr3e8uXDWUZtQ6IDfF2NkxJJGJos4IAteXbkG60q76V8pmWLCqIsMM
+tRcIpTEJUIbnbxAqSu+crZqQowu9HrJMYnqunlmXASeluxXdl8VKOVNMZHy3ipj7
+HjoTUJoiEVDLYeT7db76k2lDFH/JRtnoe3BBinUEKvGT3rOjy55C4E2DSMSM1Laz
+zkRcJ4hlzFQLXD5/iwWgW6me1lmnOEqFJZolc1fEc+VfEdZdwJmZF6Clm5av2hDm
+Oq09qL02nXy0OyAoCI6IcrrAlFFolgel32nWp1R7c+N2+6vLMP3KR50TgSiwHNNQ
+weZhpP1GrXDyVj+ilL5T/2ionvjIvDBgOi8B0IwiqeHY7lqsSyMOuKTi5WPrJ86E
+GNJ+PlivA/P9MAatem4kzCT2t3DbVC+dtybiUAmVFb2Ls+dVK4nHcbGTW9AuBijD
+COEHQgi4Xs6lnwIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQDGvq99QUxMh+DaI2Pd
+s4fQ9MmYxGDxULhjqgGAjDbL3jQMG2FxPTu1Z2VJgg4n+PTNsgsqgn1JgQM3gvFp
+8FKhoxtzM5V8pPxphCG7U/f3ZsmXdLl69sbVkMRhorhQ8H54q0O/T3Ig/ULZgblE
+xCRT1REB693tUQOCYgWgnsOpvySfujYhNBirl48Hw9zrRmQNTsO20dKwkZUvkVow
+/pawucYrHibgwgKWz8kB3Dl4DODiLybek0hGzr59Joul9eMsxTuQsHAIUv0KO2Ny
+5WT7GIX6qYc+VrnXsO+PHtx5GTUjrJiue3aggoW6X7gu3Z6KuIOiVTVLVp6wSJtt
+VHv90HTu2lYxtPyPSOpFfwFOTicN+5VmLTQwPvPRqsnCaYc+K2iWyEhN/PnSfFNc
+t/TX9HT3ljXq9yfshQmQJ27pdUiYs9Avt7fEXpJjQ0Tn9w8jRS5gsrnTUXTG6HXf
+I4lsMSAApFZa112PwU7xAIIaipBauuMjQCabD/thBzB6d29Rlbz3cjBzoky9h2vb
+XNIVo5O2Jiz7OJQ/7mubvJqIBngiaDK78n2hSdYglI1hgcf0KaQIJUridzmjt0kp
+xXcwIz7nJxhNpbsYnDnqwqz9en8a4N+KeoQleYROo2kEtE434AJkzdABV4IKRafj
+cbPWuY6F2faWAjkSOEhBfGOKOw==
+-----END CERTIFICATE-----
diff --git a/vibrator/aidl/default/apex/file_contexts b/vibrator/aidl/default/apex/file_contexts
new file mode 100644
index 0000000..f811656
--- /dev/null
+++ b/vibrator/aidl/default/apex/file_contexts
@@ -0,0 +1,3 @@
+(/.*)? 							u:object_r:vendor_file:s0
+/bin/hw/android\.hardware\.vibrator-service\.example	u:object_r:hal_vibrator_default_exec:s0
+
diff --git a/vibrator/aidl/default/fuzzer.cpp b/vibrator/aidl/default/fuzzer.cpp
new file mode 100644
index 0000000..7d52209
--- /dev/null
+++ b/vibrator/aidl/default/fuzzer.cpp
@@ -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.
+ */
+#include <fuzzbinder/libbinder_ndk_driver.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <vibrator-impl/Vibrator.h>
+#include <vibrator-impl/VibratorManager.h>
+
+using aidl::android::hardware::vibrator::Vibrator;
+using aidl::android::hardware::vibrator::VibratorManager;
+using android::fuzzService;
+using ndk::SharedRefBase;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    auto managedVib = SharedRefBase::make<Vibrator>();
+    auto vibManager = SharedRefBase::make<VibratorManager>(std::move(managedVib));
+
+    fuzzService(vibManager->asBinder().get(), FuzzedDataProvider(data, size));
+
+    return 0;
+}
diff --git a/vibrator/aidl/default/main.cpp b/vibrator/aidl/default/main.cpp
index bd834d2..feba2c7 100644
--- a/vibrator/aidl/default/main.cpp
+++ b/vibrator/aidl/default/main.cpp
@@ -31,14 +31,14 @@
     auto vib = ndk::SharedRefBase::make<Vibrator>();
     const std::string vibName = std::string() + Vibrator::descriptor + "/default";
     binder_status_t status = AServiceManager_addService(vib->asBinder().get(), vibName.c_str());
-    CHECK(status == STATUS_OK);
+    CHECK_EQ(status, STATUS_OK);
 
     // make the vibrator manager service with a different vibrator
     auto managedVib = ndk::SharedRefBase::make<Vibrator>();
     auto vibManager = ndk::SharedRefBase::make<VibratorManager>(std::move(managedVib));
     const std::string vibManagerName = std::string() + VibratorManager::descriptor + "/default";
     status = AServiceManager_addService(vibManager->asBinder().get(), vibManagerName.c_str());
-    CHECK(status == STATUS_OK);
+    CHECK_EQ(status, STATUS_OK);
 
     ABinderProcess_joinThreadPool();
     return EXIT_FAILURE;  // should not reach
diff --git a/vibrator/aidl/default/vibrator-default.rc b/vibrator/aidl/default/vibrator-default.rc
index d17f468..9e6def3 100644
--- a/vibrator/aidl/default/vibrator-default.rc
+++ b/vibrator/aidl/default/vibrator-default.rc
@@ -1,4 +1,4 @@
 service vendor.vibrator-default /vendor/bin/hw/android.hardware.vibrator-service.example
     class hal
-    user system
-    group system
+    user nobody
+    group nobody
diff --git a/vibrator/aidl/vts/Android.bp b/vibrator/aidl/vts/Android.bp
index 3f328fa..1261870 100644
--- a/vibrator/aidl/vts/Android.bp
+++ b/vibrator/aidl/vts/Android.bp
@@ -13,6 +13,7 @@
         "VtsHalTargetTestDefaults",
         "use_libaidlvintf_gtest_helper_static",
     ],
+    tidy_timeout_srcs: ["VtsHalVibratorTargetTest.cpp"],
     srcs: ["VtsHalVibratorTargetTest.cpp"],
     shared_libs: [
         "libbinder",
diff --git a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
index 553d7f0..3841715 100644
--- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
@@ -167,9 +167,9 @@
         EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
     }
 
-    float freqMaximumHz =
-        (bandwidthAmplitudeMap.size() * getFrequencyResolutionHz(vibrator, capabilities)) +
-        getFrequencyMinimumHz(vibrator, capabilities);
+    float freqMaximumHz = ((bandwidthAmplitudeMap.size() - 1) *
+                           getFrequencyResolutionHz(vibrator, capabilities)) +
+                          getFrequencyMinimumHz(vibrator, capabilities);
     return freqMaximumHz;
 }
 
@@ -196,7 +196,7 @@
     active.startFrequency = frequencyHz;
     active.endAmplitude = (getAmplitudeMin() + getAmplitudeMax()) / 2;
     active.endFrequency = frequencyHz;
-    active.duration = 1000;
+    vibrator->getPwlePrimitiveDurationMax(&(active.duration));
 
     return active;
 }
@@ -417,6 +417,9 @@
 
             if (isPrimitiveSupported) {
                 EXPECT_EQ(Status::EX_NONE, status.exceptionCode());
+                if (primitive != CompositePrimitive::NOOP) {
+                    ASSERT_GT(duration, 0) << toString(primitive) << " " << duration;
+                }
             } else {
                 EXPECT_TRUE(isUnknownOrUnsupported(status)) << status;
             }
@@ -717,27 +720,33 @@
 
 TEST_P(VibratorAidl, ComposeValidPwle) {
     if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
-        ActivePwle active = composeValidActivePwle(vibrator, capabilities);
+        ActivePwle firstActive = composeValidActivePwle(vibrator, capabilities);
 
         std::vector<Braking> supported;
         ASSERT_TRUE(vibrator->getSupportedBraking(&supported).isOk());
         bool isClabSupported =
             std::find(supported.begin(), supported.end(), Braking::CLAB) != supported.end();
-        BrakingPwle braking;
-        braking.braking = isClabSupported ? Braking::CLAB : Braking::NONE;
-        braking.duration = 100;
+        BrakingPwle firstBraking;
+        firstBraking.braking = isClabSupported ? Braking::CLAB : Braking::NONE;
+        firstBraking.duration = 100;
 
-        std::vector<PrimitivePwle> pwleQueue;
-        PrimitivePwle pwle;
-        pwle = active;
-        pwleQueue.emplace_back(std::move(pwle));
-        pwle = braking;
-        pwleQueue.emplace_back(std::move(pwle));
-        pwle = active;
-        pwleQueue.emplace_back(std::move(pwle));
+        ActivePwle secondActive = composeValidActivePwle(vibrator, capabilities);
+        if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
+            float minFrequencyHz = getFrequencyMinimumHz(vibrator, capabilities);
+            float maxFrequencyHz = getFrequencyMaximumHz(vibrator, capabilities);
+            float freqResolutionHz = getFrequencyResolutionHz(vibrator, capabilities);
+            secondActive.startFrequency = minFrequencyHz + (freqResolutionHz / 2.0f);
+            secondActive.endFrequency = maxFrequencyHz - (freqResolutionHz / 3.0f);
+        }
+        BrakingPwle secondBraking;
+        secondBraking.braking = Braking::NONE;
+        secondBraking.duration = 10;
+
+        auto pwleQueue =
+            std::vector<PrimitivePwle>{firstActive, firstBraking, secondActive, secondBraking};
 
         EXPECT_EQ(Status::EX_NONE, vibrator->composePwle(pwleQueue, nullptr).exceptionCode());
-        vibrator->off();
+        EXPECT_TRUE(vibrator->off().isOk());
     }
 }
 
@@ -750,7 +759,9 @@
     std::future<void> completionFuture{completionPromise.get_future()};
     sp<CompletionCallback> callback =
         new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
-    uint32_t durationMs = 2100;  // Sum of 2 active and 1 braking below
+    int32_t segmentDurationMaxMs;
+    vibrator->getPwlePrimitiveDurationMax(&segmentDurationMaxMs);
+    uint32_t durationMs = segmentDurationMaxMs * 2 + 100;  // Sum of 2 active and 1 braking below
     //TODO(b/187207798): revert back to conservative timeout values once
     //latencies have been fixed
     std::chrono::milliseconds timeout{durationMs * 4};
@@ -765,14 +776,7 @@
     braking.braking = isClabSupported ? Braking::CLAB : Braking::NONE;
     braking.duration = 100;
 
-    std::vector<PrimitivePwle> pwleQueue;
-    PrimitivePwle pwle;
-    pwle = active;
-    pwleQueue.emplace_back(std::move(pwle));
-    pwle = braking;
-    pwleQueue.emplace_back(std::move(pwle));
-    pwle = active;
-    pwleQueue.emplace_back(std::move(pwle));
+    auto pwleQueue = std::vector<PrimitivePwle>{active, braking, active};
 
     EXPECT_TRUE(vibrator->composePwle(pwleQueue, callback).isOk());
     EXPECT_EQ(completionFuture.wait_for(timeout), std::future_status::ready);
@@ -785,7 +789,7 @@
         // test empty queue
         EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
                   vibrator->composePwle(pwleQueue, nullptr).exceptionCode());
-        vibrator->off();
+        EXPECT_TRUE(vibrator->off().isOk());
 
         ActivePwle active = composeValidActivePwle(vibrator, capabilities);
 
@@ -801,7 +805,7 @@
 
         EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
                   vibrator->composePwle(pwleQueue, nullptr).exceptionCode());
-        vibrator->off();
+        EXPECT_TRUE(vibrator->off().isOk());
     }
 }
 
@@ -811,25 +815,20 @@
         active.startAmplitude = getAmplitudeMax() + 1.0;  // Amplitude greater than allowed
         active.endAmplitude = getAmplitudeMax() + 1.0;    // Amplitude greater than allowed
 
-        std::vector<PrimitivePwle> pwleQueueGreater;
-        PrimitivePwle pwle;
-        pwle = active;
-        pwleQueueGreater.emplace_back(std::move(pwle));
+        auto pwleQueueGreater = std::vector<PrimitivePwle>{active};
 
         EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
                   vibrator->composePwle(pwleQueueGreater, nullptr).exceptionCode());
-        vibrator->off();
+        EXPECT_TRUE(vibrator->off().isOk());
 
         active.startAmplitude = getAmplitudeMin() - 1.0;  // Amplitude less than allowed
         active.endAmplitude = getAmplitudeMin() - 1.0;    // Amplitude less than allowed
 
-        std::vector<PrimitivePwle> pwleQueueLess;
-        pwle = active;
-        pwleQueueLess.emplace_back(std::move(pwle));
+        auto pwleQueueLess = std::vector<PrimitivePwle>{active};
 
         EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
                   vibrator->composePwle(pwleQueueLess, nullptr).exceptionCode());
-        vibrator->off();
+        EXPECT_TRUE(vibrator->off().isOk());
     }
 }
 
@@ -845,25 +844,20 @@
             freqMaximumHz + freqResolutionHz;                    // Frequency greater than allowed
         active.endFrequency = freqMaximumHz + freqResolutionHz;  // Frequency greater than allowed
 
-        std::vector<PrimitivePwle> pwleQueueGreater;
-        PrimitivePwle pwle;
-        pwle = active;
-        pwleQueueGreater.emplace_back(std::move(pwle));
+        auto pwleQueueGreater = std::vector<PrimitivePwle>{active};
 
         EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
                   vibrator->composePwle(pwleQueueGreater, nullptr).exceptionCode());
-        vibrator->off();
+        EXPECT_TRUE(vibrator->off().isOk());
 
         active.startFrequency = freqMinimumHz - freqResolutionHz;  // Frequency less than allowed
         active.endFrequency = freqMinimumHz - freqResolutionHz;    // Frequency less than allowed
 
-        std::vector<PrimitivePwle> pwleQueueLess;
-        pwle = active;
-        pwleQueueLess.emplace_back(std::move(pwle));
+        auto pwleQueueLess = std::vector<PrimitivePwle>{active};
 
         EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
                   vibrator->composePwle(pwleQueueLess, nullptr).exceptionCode());
-        vibrator->off();
+        EXPECT_TRUE(vibrator->off().isOk());
     }
 }
 
@@ -871,18 +865,15 @@
     if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
         ActivePwle active = composeValidActivePwle(vibrator, capabilities);
 
-        int segmentDurationMaxMs;
+        int32_t segmentDurationMaxMs;
         vibrator->getPwlePrimitiveDurationMax(&segmentDurationMaxMs);
         active.duration = segmentDurationMaxMs + 10;  // Segment duration greater than allowed
 
-        std::vector<PrimitivePwle> pwleQueue;
-        PrimitivePwle pwle;
-        pwle = active;
-        pwleQueue.emplace_back(std::move(pwle));
+        auto pwleQueue = std::vector<PrimitivePwle>{active};
 
         EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
                   vibrator->composePwle(pwleQueue, nullptr).exceptionCode());
-        vibrator->off();
+        EXPECT_TRUE(vibrator->off().isOk());
     }
 }
 
diff --git a/weaver/1.0/vts/functional/OWNERS b/weaver/1.0/vts/functional/OWNERS
new file mode 100644
index 0000000..ec8c304
--- /dev/null
+++ b/weaver/1.0/vts/functional/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 186411
+chengyouho@google.com
+frankwoo@google.com
diff --git a/weaver/aidl/default/Android.bp b/weaver/aidl/default/Android.bp
index 37a9c94..70d9171 100644
--- a/weaver/aidl/default/Android.bp
+++ b/weaver/aidl/default/Android.bp
@@ -34,7 +34,7 @@
         "Weaver.cpp",
     ],
     shared_libs: [
-        "android.hardware.weaver-V1-ndk_platform",
+        "android.hardware.weaver-V1-ndk",
         "libbase",
         "libbinder_ndk",
     ],
diff --git a/weaver/aidl/default/Weaver.cpp b/weaver/aidl/default/Weaver.cpp
index 56d9c4d..6b77924 100644
--- a/weaver/aidl/default/Weaver.cpp
+++ b/weaver/aidl/default/Weaver.cpp
@@ -15,30 +15,52 @@
  */
 
 #include "Weaver.h"
+#include <array>
 
 namespace aidl {
 namespace android {
 namespace hardware {
 namespace weaver {
 
+struct Slotinfo {
+    int slot_id;
+    std::vector<uint8_t> key;
+    std::vector<uint8_t> value;
+};
+
+std::array<struct Slotinfo, 16> slot_array;
 // Methods from ::android::hardware::weaver::IWeaver follow.
 
 ::ndk::ScopedAStatus Weaver::getConfig(WeaverConfig* out_config) {
-    (void)out_config;
+    *out_config = {16, 16, 16};
     return ::ndk::ScopedAStatus::ok();
 }
 
 ::ndk::ScopedAStatus Weaver::read(int32_t in_slotId, const std::vector<uint8_t>& in_key, WeaverReadResponse* out_response) {
-    (void)in_slotId;
-    (void)in_key;
-    (void)out_response;
+
+    if (in_slotId > 15 || in_key.size() > 16) {
+        *out_response = {0, {}};
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(Weaver::STATUS_FAILED));
+    }
+
+    if (slot_array[in_slotId].key != in_key) {
+        *out_response = {0, {}};
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(Weaver::STATUS_INCORRECT_KEY));
+    }
+
+    *out_response = {0, slot_array[in_slotId].value};
+
     return ::ndk::ScopedAStatus::ok();
 }
 
 ::ndk::ScopedAStatus Weaver::write(int32_t in_slotId, const std::vector<uint8_t>& in_key, const std::vector<uint8_t>& in_value) {
-    (void)in_slotId;
-    (void)in_key;
-    (void)in_value;
+
+    if (in_slotId > 15 || in_key.size() > 16 || in_value.size() > 16)
+        return ::ndk::ScopedAStatus::fromStatus(STATUS_FAILED_TRANSACTION);
+
+    slot_array[in_slotId].key = in_key;
+    slot_array[in_slotId].value = in_value;
+
     return ::ndk::ScopedAStatus::ok();
 }
 
diff --git a/weaver/aidl/default/service.cpp b/weaver/aidl/default/service.cpp
index 1495bc9..2099ffd 100644
--- a/weaver/aidl/default/service.cpp
+++ b/weaver/aidl/default/service.cpp
@@ -28,7 +28,7 @@
 
     const std::string instance = std::string() + Weaver::descriptor + "/default";
     binder_status_t status = AServiceManager_addService(weaver->asBinder().get(), instance.c_str());
-    CHECK(status == STATUS_OK);
+    CHECK_EQ(status, STATUS_OK);
 
     ABinderProcess_joinThreadPool();
     return -1; // Should never be reached
diff --git a/weaver/aidl/vts/Android.bp b/weaver/aidl/vts/Android.bp
index 8dec4c1..cf1661c 100644
--- a/weaver/aidl/vts/Android.bp
+++ b/weaver/aidl/vts/Android.bp
@@ -34,7 +34,7 @@
         "libbinder_ndk",
         "libbase",
     ],
-    static_libs: ["android.hardware.weaver-V1-ndk_platform"],
+    static_libs: ["android.hardware.weaver-V1-ndk"],
     test_suites: [
         "general-tests",
         "vts",
diff --git a/wifi/1.0/vts/OWNERS b/wifi/1.0/vts/OWNERS
index cf81c79..287152d 100644
--- a/wifi/1.0/vts/OWNERS
+++ b/wifi/1.0/vts/OWNERS
@@ -1,2 +1,3 @@
+# Bug component: 33618
 arabawy@google.com
 etancohen@google.com
diff --git a/wifi/1.0/vts/functional/Android.bp b/wifi/1.0/vts/functional/Android.bp
index 6c0ebf7..ebfa164 100644
--- a/wifi/1.0/vts/functional/Android.bp
+++ b/wifi/1.0/vts/functional/Android.bp
@@ -48,6 +48,9 @@
 cc_test {
     name: "VtsHalWifiV1_0TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: [
+        "wifi_chip_hidl_test.cpp",
+    ],
     srcs: [
         "wifi_chip_hidl_test.cpp",
         "wifi_p2p_iface_hidl_test.cpp",
diff --git a/wifi/1.1/vts/OWNERS b/wifi/1.1/vts/OWNERS
index cf81c79..294fc82 100644
--- a/wifi/1.1/vts/OWNERS
+++ b/wifi/1.1/vts/OWNERS
@@ -1,2 +1,2 @@
-arabawy@google.com
-etancohen@google.com
+# Bug component: 33618
+include ../../1.0/vts/OWNERS
diff --git a/wifi/1.2/vts/OWNERS b/wifi/1.2/vts/OWNERS
index cf81c79..294fc82 100644
--- a/wifi/1.2/vts/OWNERS
+++ b/wifi/1.2/vts/OWNERS
@@ -1,2 +1,2 @@
-arabawy@google.com
-etancohen@google.com
+# Bug component: 33618
+include ../../1.0/vts/OWNERS
diff --git a/wifi/1.3/vts/OWNERS b/wifi/1.3/vts/OWNERS
index cf81c79..294fc82 100644
--- a/wifi/1.3/vts/OWNERS
+++ b/wifi/1.3/vts/OWNERS
@@ -1,2 +1,2 @@
-arabawy@google.com
-etancohen@google.com
+# Bug component: 33618
+include ../../1.0/vts/OWNERS
diff --git a/wifi/1.4/vts/OWNERS b/wifi/1.4/vts/OWNERS
index cf81c79..294fc82 100644
--- a/wifi/1.4/vts/OWNERS
+++ b/wifi/1.4/vts/OWNERS
@@ -1,2 +1,2 @@
-arabawy@google.com
-etancohen@google.com
+# Bug component: 33618
+include ../../1.0/vts/OWNERS
diff --git a/wifi/1.5/default/Android.bp b/wifi/1.5/default/Android.bp
new file mode 100644
index 0000000..6333b6e
--- /dev/null
+++ b/wifi/1.5/default/Android.bp
@@ -0,0 +1,105 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+filegroup {
+    name: "android.hardware.wifi@1.0-service_srcs",
+    srcs: ["service.cpp"],
+}
+
+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",
+        "libbase",
+        "libcutils",
+        "libhidlbase",
+        "liblog",
+        "libnl",
+        "libutils",
+        "libwifi-system-iface",
+        "libxml2",
+    ],
+    cppflags: [
+        "-Wall",
+        "-Werror",
+        "-Wextra",
+    ],
+}
+
+filegroup {
+    name: "android.hardware.wifi@1.0-service-lib_srcs",
+    srcs: [
+        "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",
+    ],
+}
+
+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: [
+        "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",
+        "libbase",
+        "libcutils",
+        "libhidlbase",
+        "liblog",
+        "libnl",
+        "libutils",
+        "libwifi-system-iface",
+        "libxml2",
+    ],
+    // Generated by building android.hardware.wifi@1.0-service-lib and printing LOCAL_CPPFLAGS.
+    cppflags: [
+        "-Wall",
+        "-Werror",
+        "-Wextra",
+        "-DWIFI_HIDL_FEATURE_DUAL_INTERFACE",
+    ],
+    export_include_dirs: ["."],
+    include_dirs: ["external/libxml2/include"],
+}
diff --git a/wifi/1.5/default/wifi.h b/wifi/1.5/default/wifi.h
index 840bdfd..c94ef3f 100644
--- a/wifi/1.5/default/wifi.h
+++ b/wifi/1.5/default/wifi.h
@@ -17,11 +17,15 @@
 #ifndef WIFI_H_
 #define WIFI_H_
 
-#include <functional>
+// HACK: NAN is a macro defined in math.h, which can be included in various
+// headers. This wifi HAL uses an enum called NAN, which does not compile when
+// the macro is defined. Undefine NAN to work around it.
+#undef NAN
+#include <android/hardware/wifi/1.5/IWifi.h>
 
 #include <android-base/macros.h>
-#include <android/hardware/wifi/1.5/IWifi.h>
 #include <utils/Looper.h>
+#include <functional>
 
 #include "hidl_callback_util.h"
 #include "wifi_chip.h"
diff --git a/wifi/1.5/vts/OWNERS b/wifi/1.5/vts/OWNERS
index cf81c79..294fc82 100644
--- a/wifi/1.5/vts/OWNERS
+++ b/wifi/1.5/vts/OWNERS
@@ -1,2 +1,2 @@
-arabawy@google.com
-etancohen@google.com
+# Bug component: 33618
+include ../../1.0/vts/OWNERS
diff --git a/wifi/hostapd/1.0/vts/OWNERS b/wifi/hostapd/1.0/vts/OWNERS
index cf81c79..287152d 100644
--- a/wifi/hostapd/1.0/vts/OWNERS
+++ b/wifi/hostapd/1.0/vts/OWNERS
@@ -1,2 +1,3 @@
+# Bug component: 33618
 arabawy@google.com
 etancohen@google.com
diff --git a/wifi/hostapd/1.1/vts/OWNERS b/wifi/hostapd/1.1/vts/OWNERS
index cf81c79..294fc82 100644
--- a/wifi/hostapd/1.1/vts/OWNERS
+++ b/wifi/hostapd/1.1/vts/OWNERS
@@ -1,2 +1,2 @@
-arabawy@google.com
-etancohen@google.com
+# Bug component: 33618
+include ../../1.0/vts/OWNERS
diff --git a/wifi/hostapd/1.2/vts/OWNERS b/wifi/hostapd/1.2/vts/OWNERS
index cf81c79..294fc82 100644
--- a/wifi/hostapd/1.2/vts/OWNERS
+++ b/wifi/hostapd/1.2/vts/OWNERS
@@ -1,2 +1,2 @@
-arabawy@google.com
-etancohen@google.com
+# Bug component: 33618
+include ../../1.0/vts/OWNERS
diff --git a/wifi/hostapd/1.3/vts/OWNERS b/wifi/hostapd/1.3/vts/OWNERS
index cf81c79..294fc82 100644
--- a/wifi/hostapd/1.3/vts/OWNERS
+++ b/wifi/hostapd/1.3/vts/OWNERS
@@ -1,2 +1,2 @@
-arabawy@google.com
-etancohen@google.com
+# Bug component: 33618
+include ../../1.0/vts/OWNERS
diff --git a/wifi/hostapd/1.3/vts/functional/Android.bp b/wifi/hostapd/1.3/vts/functional/Android.bp
index 6eceadf..78cd4af 100644
--- a/wifi/hostapd/1.3/vts/functional/Android.bp
+++ b/wifi/hostapd/1.3/vts/functional/Android.bp
@@ -26,6 +26,9 @@
 cc_test {
     name: "VtsHalWifiHostapdV1_3TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: [
+        "hostapd_hidl_test.cpp",
+    ],
     srcs: [
         "hostapd_hidl_test.cpp",
     ],
diff --git a/wifi/hostapd/aidl/Android.bp b/wifi/hostapd/aidl/Android.bp
new file mode 100644
index 0000000..fcd06ff
--- /dev/null
+++ b/wifi/hostapd/aidl/Android.bp
@@ -0,0 +1,46 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+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.hostapd",
+    vendor_available: true,
+    srcs: [
+        "android/hardware/wifi/hostapd/*.aidl",
+    ],
+    stability: "vintf",
+    backend: {
+        java: {
+            sdk_version: "module_current",
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.wifi",
+            ],
+            min_sdk_version: "30",
+        },
+        ndk: {
+            vndk: {
+                enabled: true,
+            },
+        },
+    },
+}
diff --git a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/ApInfo.aidl b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/ApInfo.aidl
new file mode 100644
index 0000000..bdbaadd
--- /dev/null
+++ b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/ApInfo.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.hostapd;
+@VintfStability
+parcelable ApInfo {
+  String ifaceName;
+  String apIfaceInstance;
+  int freqMhz;
+  android.hardware.wifi.hostapd.Bandwidth bandwidth;
+  android.hardware.wifi.hostapd.Generation generation;
+  byte[] apIfaceInstanceMacAddress;
+}
diff --git a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/BandMask.aidl b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/BandMask.aidl
new file mode 100644
index 0000000..b1e7f66
--- /dev/null
+++ b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/BandMask.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.hostapd;
+@Backing(type="int") @VintfStability
+enum BandMask {
+  BAND_2_GHZ = 1,
+  BAND_5_GHZ = 2,
+  BAND_6_GHZ = 4,
+  BAND_60_GHZ = 8,
+}
diff --git a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/Bandwidth.aidl b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/Bandwidth.aidl
new file mode 100644
index 0000000..890d986
--- /dev/null
+++ b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/Bandwidth.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.hostapd;
+@Backing(type="int") @VintfStability
+enum Bandwidth {
+  BANDWIDTH_INVALID = 0,
+  BANDWIDTH_20_NOHT = 1,
+  BANDWIDTH_20 = 2,
+  BANDWIDTH_40 = 3,
+  BANDWIDTH_80 = 4,
+  BANDWIDTH_80P80 = 5,
+  BANDWIDTH_160 = 6,
+  BANDWIDTH_2160 = 7,
+  BANDWIDTH_4320 = 8,
+  BANDWIDTH_6480 = 9,
+  BANDWIDTH_8640 = 10,
+}
diff --git a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/ChannelParams.aidl b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/ChannelParams.aidl
new file mode 100644
index 0000000..43a9ada
--- /dev/null
+++ b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/ChannelParams.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.hostapd;
+@VintfStability
+parcelable ChannelParams {
+  android.hardware.wifi.hostapd.BandMask bandMask;
+  android.hardware.wifi.hostapd.FrequencyRange[] acsChannelFreqRangesMhz;
+  boolean enableAcs;
+  boolean acsShouldExcludeDfs;
+  int channel;
+}
diff --git a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/ClientInfo.aidl b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/ClientInfo.aidl
new file mode 100644
index 0000000..c4d62b6
--- /dev/null
+++ b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/ClientInfo.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.hostapd;
+@VintfStability
+parcelable ClientInfo {
+  String ifaceName;
+  String apIfaceInstance;
+  byte[] clientAddress;
+  boolean isConnected;
+}
diff --git a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/DebugLevel.aidl b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/DebugLevel.aidl
new file mode 100644
index 0000000..9795211
--- /dev/null
+++ b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/DebugLevel.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.hostapd;
+@Backing(type="int") @VintfStability
+enum DebugLevel {
+  EXCESSIVE = 0,
+  MSGDUMP = 1,
+  DEBUG = 2,
+  INFO = 3,
+  WARNING = 4,
+  ERROR = 5,
+}
diff --git a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/EncryptionType.aidl b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/EncryptionType.aidl
new file mode 100644
index 0000000..cec0c14
--- /dev/null
+++ b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/EncryptionType.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.hostapd;
+@Backing(type="int") @VintfStability
+enum EncryptionType {
+  NONE = 0,
+  WPA = 1,
+  WPA2 = 2,
+  WPA3_SAE_TRANSITION = 3,
+  WPA3_SAE = 4,
+}
diff --git a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/FrequencyRange.aidl b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/FrequencyRange.aidl
new file mode 100644
index 0000000..1185143
--- /dev/null
+++ b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/FrequencyRange.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.hostapd;
+@VintfStability
+parcelable FrequencyRange {
+  int startMhz;
+  int endMhz;
+}
diff --git a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/Generation.aidl b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/Generation.aidl
new file mode 100644
index 0000000..6b60d17
--- /dev/null
+++ b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/Generation.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.hostapd;
+@Backing(type="int") @VintfStability
+enum Generation {
+  WIFI_STANDARD_UNKNOWN = -1,
+  WIFI_STANDARD_LEGACY = 0,
+  WIFI_STANDARD_11N = 1,
+  WIFI_STANDARD_11AC = 2,
+  WIFI_STANDARD_11AX = 3,
+  WIFI_STANDARD_11AD = 4,
+}
diff --git a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/HostapdStatusCode.aidl b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/HostapdStatusCode.aidl
new file mode 100644
index 0000000..548e497
--- /dev/null
+++ b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/HostapdStatusCode.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.hostapd;
+@Backing(type="int") @VintfStability
+enum HostapdStatusCode {
+  SUCCESS = 0,
+  FAILURE_UNKNOWN = 1,
+  FAILURE_ARGS_INVALID = 2,
+  FAILURE_IFACE_UNKNOWN = 3,
+  FAILURE_IFACE_EXISTS = 4,
+  FAILURE_CLIENT_UNKNOWN = 5,
+}
diff --git a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/HwModeParams.aidl b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/HwModeParams.aidl
new file mode 100644
index 0000000..844c838
--- /dev/null
+++ b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/HwModeParams.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.hostapd;
+@VintfStability
+parcelable HwModeParams {
+  boolean enable80211N;
+  boolean enable80211AC;
+  boolean enable80211AX;
+  boolean enable6GhzBand;
+  boolean enableHeSingleUserBeamformer;
+  boolean enableHeSingleUserBeamformee;
+  boolean enableHeMultiUserBeamformer;
+  boolean enableHeTargetWakeTime;
+  boolean enableEdmg;
+}
diff --git a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/IHostapd.aidl b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/IHostapd.aidl
new file mode 100644
index 0000000..ff941fd
--- /dev/null
+++ b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/IHostapd.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.hostapd;
+@VintfStability
+interface IHostapd {
+  void addAccessPoint(in android.hardware.wifi.hostapd.IfaceParams ifaceParams, in android.hardware.wifi.hostapd.NetworkParams nwParams);
+  void forceClientDisconnect(in String ifaceName, in byte[] clientAddress, in android.hardware.wifi.hostapd.Ieee80211ReasonCode reasonCode);
+  void registerCallback(in android.hardware.wifi.hostapd.IHostapdCallback callback);
+  void removeAccessPoint(in String ifaceName);
+  void setDebugParams(in android.hardware.wifi.hostapd.DebugLevel level);
+  oneway void terminate();
+}
diff --git a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/IHostapdCallback.aidl b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/IHostapdCallback.aidl
new file mode 100644
index 0000000..36d2104
--- /dev/null
+++ b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/IHostapdCallback.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.hostapd;
+@VintfStability
+interface IHostapdCallback {
+  oneway void onApInstanceInfoChanged(in android.hardware.wifi.hostapd.ApInfo apInfo);
+  oneway void onConnectedClientsChanged(in android.hardware.wifi.hostapd.ClientInfo clientInfo);
+  oneway void onFailure(in String ifaceName);
+}
diff --git a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/Ieee80211ReasonCode.aidl b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/Ieee80211ReasonCode.aidl
new file mode 100644
index 0000000..99879b5
--- /dev/null
+++ b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/Ieee80211ReasonCode.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.hostapd;
+@Backing(type="int") @VintfStability
+enum Ieee80211ReasonCode {
+  WLAN_REASON_UNSPECIFIED = 1,
+  WLAN_REASON_PREV_AUTH_NOT_VALID = 2,
+  WLAN_REASON_DISASSOC_AP_BUSY = 5,
+}
diff --git a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/IfaceParams.aidl b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/IfaceParams.aidl
new file mode 100644
index 0000000..0c88a39
--- /dev/null
+++ b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/IfaceParams.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.hostapd;
+@VintfStability
+parcelable IfaceParams {
+  String name;
+  android.hardware.wifi.hostapd.HwModeParams hwModeParams;
+  android.hardware.wifi.hostapd.ChannelParams[] channelParams;
+}
diff --git a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/NetworkParams.aidl b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/NetworkParams.aidl
new file mode 100644
index 0000000..ffe2f33
--- /dev/null
+++ b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/NetworkParams.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.hostapd;
+@VintfStability
+parcelable NetworkParams {
+  byte[] ssid;
+  boolean isHidden;
+  android.hardware.wifi.hostapd.EncryptionType encryptionType;
+  String passphrase;
+  boolean isMetered;
+}
diff --git a/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/ParamSizeLimits.aidl b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/ParamSizeLimits.aidl
new file mode 100644
index 0000000..70f94c1
--- /dev/null
+++ b/wifi/hostapd/aidl/aidl_api/android.hardware.wifi.hostapd/current/android/hardware/wifi/hostapd/ParamSizeLimits.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.hostapd;
+@Backing(type="int") @VintfStability
+enum ParamSizeLimits {
+  SSID_MAX_LEN_IN_BYTES = 32,
+  WPA2_PSK_PASSPHRASE_MIN_LEN_IN_BYTES = 8,
+  WPA2_PSK_PASSPHRASE_MAX_LEN_IN_BYTES = 63,
+}
diff --git a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/ApInfo.aidl b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/ApInfo.aidl
new file mode 100644
index 0000000..bf506b2
--- /dev/null
+++ b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/ApInfo.aidl
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.hostapd;
+
+import android.hardware.wifi.hostapd.Bandwidth;
+import android.hardware.wifi.hostapd.Generation;
+
+/**
+ * Parameters to control the channel selection for the interface.
+ */
+@VintfStability
+parcelable ApInfo {
+    /**
+     * Name of the interface which was added via |IHostapd.addAccessPoint|.
+     */
+    String ifaceName;
+
+    /**
+     * The identity of the AP instance. The interface will have two instances
+     * (e.g. 2.4 Ghz AP and 5 GHz AP) in dual AP mode.
+     * The apIfaceInstance can be used to identify which instance the callback
+     * is from.
+     * Note: The apIfaceInstance must be same as ifaceName in single AP mode.
+     */
+    String apIfaceInstance;
+
+    /**
+     * The operational frequency of the AP in Mhz.
+     */
+    int freqMhz;
+
+    /**
+     * The operational bandwidth of the AP.
+     */
+    Bandwidth bandwidth;
+
+    /**
+     * The operational mode of the AP (e.g. 11ac, 11ax).
+     */
+    Generation generation;
+
+    /**
+     * MAC Address of the apIfaceInstance.
+     */
+    byte[] apIfaceInstanceMacAddress;
+}
diff --git a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/BandMask.aidl b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/BandMask.aidl
new file mode 100644
index 0000000..0c64bd1
--- /dev/null
+++ b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/BandMask.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.hostapd;
+
+@VintfStability
+@Backing(type="int")
+enum BandMask {
+    /**
+     * 2.4 GHz band.
+     */
+    BAND_2_GHZ = 1 << 0,
+    /**
+     * 5 GHz band.
+     */
+    BAND_5_GHZ = 1 << 1,
+    /**
+     * 6 GHz band.
+     */
+    BAND_6_GHZ = 1 << 2,
+    /**
+     * 60 GHz band.
+     */
+    BAND_60_GHZ = 1 << 3,
+}
diff --git a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/Bandwidth.aidl b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/Bandwidth.aidl
new file mode 100644
index 0000000..c982402
--- /dev/null
+++ b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/Bandwidth.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.hostapd;
+
+/**
+ * The channel bandwidth of the AP.
+ */
+@VintfStability
+@Backing(type="int")
+enum Bandwidth {
+    BANDWIDTH_INVALID = 0,
+    BANDWIDTH_20_NOHT = 1,
+    BANDWIDTH_20 = 2,
+    BANDWIDTH_40 = 3,
+    BANDWIDTH_80 = 4,
+    BANDWIDTH_80P80 = 5,
+    BANDWIDTH_160 = 6,
+    BANDWIDTH_2160 = 7,
+    BANDWIDTH_4320 = 8,
+    BANDWIDTH_6480 = 9,
+    BANDWIDTH_8640 = 10,
+}
diff --git a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/ChannelParams.aidl b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/ChannelParams.aidl
new file mode 100644
index 0000000..b2e0c81
--- /dev/null
+++ b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/ChannelParams.aidl
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.hostapd;
+
+import android.hardware.wifi.hostapd.BandMask;
+import android.hardware.wifi.hostapd.FrequencyRange;
+
+/**
+ * Parameters to control the channel selection for the interface.
+ */
+@VintfStability
+parcelable ChannelParams {
+    /**
+     * Band to use for the SoftAp operations.
+     */
+    BandMask bandMask;
+    /**
+     * This option can be used to specify the channel frequencies (in MHz) selected by ACS.
+     * If this is an empty list, all channels allowed in selected HW mode
+     * are specified implicitly.
+     * Note: channels may be overridden by firmware.
+     * Note: this option is ignored if ACS is disabled.
+     */
+    FrequencyRange[] acsChannelFreqRangesMhz;
+    /**
+     * Whether to enable ACS (Automatic Channel Selection) or not.
+     * The channel can be selected automatically at run time by setting
+     * this flag, which must enable the ACS survey based algorithm.
+     */
+    boolean enableAcs;
+    /**
+     * This option can be used to exclude all DFS channels from the ACS
+     * channel list in cases where the driver supports DFS channels.
+     **/
+    boolean acsShouldExcludeDfs;
+    /**
+     * Channel number (IEEE 802.11) to use for the interface.
+     * If ACS is enabled, this field is ignored.
+     *
+     * If |enableEdmg| is true, the channel must be set. Refer to
+     * P802.11ay_D4.0 29.3.4.
+     */
+    int channel;
+}
diff --git a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/ClientInfo.aidl b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/ClientInfo.aidl
new file mode 100644
index 0000000..7bed658
--- /dev/null
+++ b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/ClientInfo.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.hostapd;
+
+/**
+ * Parameters to control the channel selection for the interface.
+ */
+@VintfStability
+parcelable ClientInfo {
+    /**
+     * Name of the interface which was added via |IHostapd.addAccessPoint|.
+     */
+    String ifaceName;
+
+    /**
+     * The identity of the AP instance. The interface will have two instances in dual AP mode.
+     * The apIfaceInstance can be used to identify which instance the callback is from.
+     * Note: The apIfaceInstance must be same as ifaceName in single AP mode.
+     */
+    String apIfaceInstance;
+
+    /**
+     * MAC Address of hotspot client.
+     */
+    byte[] clientAddress;
+
+    /**
+     * True when client connected, false when client disconnected.
+     */
+    boolean isConnected;
+}
diff --git a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/DebugLevel.aidl b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/DebugLevel.aidl
new file mode 100644
index 0000000..5187729
--- /dev/null
+++ b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/DebugLevel.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.hostapd;
+
+/**
+ * Debug levels for the hostapd.
+ * Only log messages with a level greater than the set level
+ * (via |setDebugParams|) will be logged.
+ */
+@VintfStability
+@Backing(type="int")
+enum DebugLevel {
+    EXCESSIVE = 0,
+    MSGDUMP = 1,
+    DEBUG = 2,
+    INFO = 3,
+    WARNING = 4,
+    ERROR = 5,
+}
diff --git a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/EncryptionType.aidl b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/EncryptionType.aidl
new file mode 100644
index 0000000..bfc634d
--- /dev/null
+++ b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/EncryptionType.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.hostapd;
+
+import android.hardware.wifi.hostapd.EncryptionType;
+
+/**
+ * Possible Security types.
+ */
+@VintfStability
+@Backing(type="int")
+enum EncryptionType {
+    NONE,
+    WPA,
+    WPA2,
+    WPA3_SAE_TRANSITION,
+    WPA3_SAE,
+}
diff --git a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/FrequencyRange.aidl b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/FrequencyRange.aidl
new file mode 100644
index 0000000..81f6744
--- /dev/null
+++ b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/FrequencyRange.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.hostapd;
+
+/**
+ * Parameters to specify the channel frequency range.
+ */
+@VintfStability
+parcelable FrequencyRange {
+    /**
+     * Channel Frequency (in MHz) at the start of the range.
+     */
+    int startMhz;
+    /**
+     * Channel Frequency (in MHz) at the end of the range.
+     */
+    int endMhz;
+}
diff --git a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/Generation.aidl b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/Generation.aidl
new file mode 100644
index 0000000..2cda55b
--- /dev/null
+++ b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/Generation.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.hostapd;
+
+/**
+ * The wifi operational mode of the AP.
+ * It depends on hw mode and HT/VHT capabilities in hostapd.
+ *
+ * WIFI_STANDARD_LEGACY = (hw_mode is HOSTAPD_MODE_IEEE80211B) or
+ *                        (hw_mode is HOSTAPD_MODE_IEEE80211G and HT is 0).
+ * WIFI_STANDARD_11N = [hw_mode is HOSTAPD_MODE_IEEE80211G and (HT is 1 or HT40 is 1)] or
+ *                     [hw_mode is HOSTAPD_MODE_IEEE80211A and VHT is 0].
+ * WIFI_STANDARD_11AC = hw_mode is HOSTAPD_MODE_IEEE80211A and VHT is 1.
+ * WIFI_STANDARD_11AX = hw_mode is HOSTAPD_MODE_IEEE80211A and High Efficiency supported.
+ * WIFI_STANDARD_11AD = hw_mode is HOSTAPD_MODE_IEEE80211AD.
+ */
+@VintfStability
+@Backing(type="int")
+enum Generation {
+    WIFI_STANDARD_UNKNOWN = -1,
+    WIFI_STANDARD_LEGACY = 0,
+    WIFI_STANDARD_11N = 1,
+    WIFI_STANDARD_11AC = 2,
+    WIFI_STANDARD_11AX = 3,
+    WIFI_STANDARD_11AD = 4,
+}
diff --git a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/HostapdStatusCode.aidl b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/HostapdStatusCode.aidl
new file mode 100644
index 0000000..87f1453
--- /dev/null
+++ b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/HostapdStatusCode.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.hostapd;
+
+/**
+ * Enum values indicating the status of any hostapd operation.
+ */
+@VintfStability
+@Backing(type="int")
+enum HostapdStatusCode {
+    /**
+     * No errors.
+     */
+    SUCCESS,
+    /**
+     * Unknown failure occurred.
+     */
+    FAILURE_UNKNOWN,
+    /**
+     * One or more of the incoming args is invalid.
+     */
+    FAILURE_ARGS_INVALID,
+    /**
+     * Interface with the provided name does not exist.
+     */
+    FAILURE_IFACE_UNKNOWN,
+    /**
+     * Interface with the provided name already exists.
+     */
+    FAILURE_IFACE_EXISTS,
+    /**
+     * Failure because the client is unknown.
+     */
+    FAILURE_CLIENT_UNKNOWN,
+}
diff --git a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/HwModeParams.aidl b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/HwModeParams.aidl
new file mode 100644
index 0000000..210e99f
--- /dev/null
+++ b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/HwModeParams.aidl
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.hostapd;
+
+/**
+ * Parameters to control the HW mode for the interface.
+ */
+@VintfStability
+parcelable HwModeParams {
+    /**
+     * Whether IEEE 802.11n (HT) is enabled or not.
+     * Note: hwMode=G (2.4 GHz) and hwMode=A (5 GHz) is used to specify
+     * the band.
+     */
+    boolean enable80211N;
+    /**
+     * Whether IEEE 802.11ac (VHT) is enabled or not.
+     * Note: hw_mode=a is used to specify that 5 GHz band is used with VHT.
+     */
+    boolean enable80211AC;
+    /**
+     * Whether IEEE 802.11ax (High Efficiency) is enabled or not.
+     * Note: hw_mode=a is used to specify that 5 GHz band or 6 GHz band is
+     * used with High Efficiency.
+     */
+    boolean enable80211AX;
+    /**
+     * Whether 6GHz band enabled or not on softAp.
+     * Note: hw_mode=a is used to specify that 5 GHz band or 6 GHz band is
+     * used.
+     */
+    boolean enable6GhzBand;
+    /**
+     * Whether High Efficiency single user beamformer in enabled or not on softAp.
+     * Note: this is only applicable if 802.11ax is supported for softAp
+     */
+    boolean enableHeSingleUserBeamformer;
+    /**
+     * Whether High Efficiency single user beamformee is enabled or not on softAp.
+     * Note: this is only applicable if 802.11ax is supported for softAp
+     */
+    boolean enableHeSingleUserBeamformee;
+    /**
+     * Whether High Efficiency multiple user beamformer is enabled or not on softAp.
+     * Note: this is only applicable if 802.11ax is supported for softAp
+     */
+    boolean enableHeMultiUserBeamformer;
+    /**
+     * Whether High Efficiency Target Wait Time (TWT) is enabled or not on softAp.
+     * Note: this is only applicable if 802.11ax is supported for softAp
+     */
+    boolean enableHeTargetWakeTime;
+    /**
+     * Enable EDMG (802.11ay), this option is only allowed for the 60GHz band.
+     */
+    boolean enableEdmg;
+}
diff --git a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/IHostapd.aidl b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/IHostapd.aidl
new file mode 100644
index 0000000..d2f4795
--- /dev/null
+++ b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/IHostapd.aidl
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.hostapd;
+
+import android.hardware.wifi.hostapd.BandMask;
+import android.hardware.wifi.hostapd.ChannelParams;
+import android.hardware.wifi.hostapd.DebugLevel;
+import android.hardware.wifi.hostapd.HwModeParams;
+import android.hardware.wifi.hostapd.IHostapdCallback;
+import android.hardware.wifi.hostapd.Ieee80211ReasonCode;
+import android.hardware.wifi.hostapd.IfaceParams;
+import android.hardware.wifi.hostapd.NetworkParams;
+
+/**
+ * Top-level interface for managing SoftAPs.
+ */
+@VintfStability
+interface IHostapd {
+    /**
+     * Adds a new access point for hostapd to control.
+     *
+     * This should trigger the setup of an access point with the specified
+     * interface and network params.
+     *
+     * @param ifaceParams AccessPoint Params for the access point.
+     * @param nwParams Network Params for the access point.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |HostapdStatusCode.FAILURE_ARGS_INVALID|,
+     *         |HostapdStatusCode.FAILURE_UNKNOWN|,
+     *         |HostapdStatusCode.FAILURE_IFACE_EXISTS|
+     */
+    void addAccessPoint(in IfaceParams ifaceParams, in NetworkParams nwParams);
+
+    /**
+     * Force one of the hotspot clients to disconnect.
+     *
+     * @param ifaceName Name of the interface.
+     * @param clientAddress MAC Address of the hotspot client.
+     * @param reasonCode One of disconnect reason code defined by 802.11.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |HostapdStatusCode.FAILURE_IFACE_UNKNOWN|,
+     *         |HostapdStatusCode.FAILURE_CLIENT_UNKNOWN|
+     */
+    void forceClientDisconnect(
+            in String ifaceName, in byte[] clientAddress, in Ieee80211ReasonCode reasonCode);
+
+    /**
+     * Register for callbacks from the hostapd service.
+     *
+     * These callbacks are invoked for global events that are not specific
+     * to any interface or network. Registration of multiple callback
+     * objects is supported. These objects must be deleted when the corresponding
+     * client process is dead.
+     *
+     * @param callback An instance of the |IHostapdCallback| AIDL interface
+     *     object.
+     * @throws ServiceSpecificException with one of the following values:
+     *     |HostapdStatusCode.FAILURE_UNKNOWN|
+     */
+    void registerCallback(in IHostapdCallback callback);
+
+    /**
+     * Removes an existing access point from hostapd.
+     *
+     * This must bring down the access point previously set up on the
+     * interface.
+     *
+     * @param ifaceName Name of the interface.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |HostapdStatusCode.FAILURE_UNKNOWN|,
+     *         |HostapdStatusCode.FAILURE_IFACE_UNKNOWN|
+     */
+    void removeAccessPoint(in String ifaceName);
+
+    /**
+     * Set debug parameters for the hostapd.
+     *
+     * @param level Debug logging level for the hostapd.
+     *        (one of |DebugLevel| values).
+     * @throws ServiceSpecificException with one of the following values:
+     *         |HostapdStatusCode.FAILURE_UNKNOWN|
+     */
+    void setDebugParams(in DebugLevel level);
+
+    /**
+     * Terminate the service.
+     * This must de-register the service and clear all states. If this HAL
+     * supports the lazy HAL protocol, then this may trigger daemon to exit and
+     * wait to be restarted.
+     */
+    oneway void terminate();
+}
diff --git a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/IHostapdCallback.aidl b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/IHostapdCallback.aidl
new file mode 100644
index 0000000..7b04944
--- /dev/null
+++ b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/IHostapdCallback.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.hostapd;
+
+import android.hardware.wifi.hostapd.ApInfo;
+import android.hardware.wifi.hostapd.ClientInfo;
+
+/**
+ * Top-level callback interface for managing SoftAPs.
+ */
+@VintfStability
+interface IHostapdCallback {
+    /**
+     * Invoked when information changes for one of the AP instances.
+     *
+     * @param apInfo AP information of the instance changed.
+     */
+    oneway void onApInstanceInfoChanged(in ApInfo apInfo);
+
+    /**
+     * Invoked when a client connects/disconnects from the hotspot.
+     *
+     */
+    oneway void onConnectedClientsChanged(in ClientInfo clientInfo);
+
+    /**
+     * Invoked when an asynchronous failure is encountered in one of the access
+     * points added via |IHostapd.addAccessPoint|.
+     *
+     * @param ifaceName Name of the interface.
+     */
+    oneway void onFailure(in String ifaceName);
+}
diff --git a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/Ieee80211ReasonCode.aidl b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/Ieee80211ReasonCode.aidl
new file mode 100644
index 0000000..a11f44a
--- /dev/null
+++ b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/Ieee80211ReasonCode.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.hostapd;
+
+/**
+ * Enum values indicating the reason code for disconnect packet.
+ * Reason codes (IEEE Std 802.11-2016, 9.4.1.7, Table 9-45).
+ */
+@VintfStability
+@Backing(type="int")
+enum Ieee80211ReasonCode {
+    WLAN_REASON_UNSPECIFIED = 1,
+    WLAN_REASON_PREV_AUTH_NOT_VALID = 2,
+    WLAN_REASON_DISASSOC_AP_BUSY = 5,
+}
diff --git a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/IfaceParams.aidl b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/IfaceParams.aidl
new file mode 100644
index 0000000..a8abec3
--- /dev/null
+++ b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/IfaceParams.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.hostapd;
+
+import android.hardware.wifi.hostapd.ChannelParams;
+import android.hardware.wifi.hostapd.HwModeParams;
+
+/**
+ * Parameters to use for setting up the dual access point interfaces.
+ */
+@VintfStability
+parcelable IfaceParams {
+    /**
+     * Name of the interface
+     */
+    String name;
+    /**
+     * Additional hardware mode params for the interface
+     */
+    HwModeParams hwModeParams;
+    /**
+     * The list of the channel params for the dual interfaces.
+     */
+    ChannelParams[] channelParams;
+}
diff --git a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/NetworkParams.aidl b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/NetworkParams.aidl
new file mode 100644
index 0000000..df84eca
--- /dev/null
+++ b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/NetworkParams.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.hostapd;
+
+import android.hardware.wifi.hostapd.EncryptionType;
+
+/**
+ * Parameters to use for setting up the access point network.
+ */
+@VintfStability
+parcelable NetworkParams {
+    /**
+     * SSID to set for the network
+     */
+    byte[] ssid;
+    /**
+     * Whether the network needs to be hidden or not.
+     */
+    boolean isHidden;
+    /**
+     * Key management mask for the replace encryptionType.
+     */
+    EncryptionType encryptionType;
+    /**
+     * Passphrase for WPA3_SAE network, WPA3_SAE_TRANSITION and WPA2_PSK.
+     */
+    String passphrase;
+    /**
+     * Enable the interworking service and set access network type to
+     * CHARGEABLE_PUBLIC_NETWORK when set to true.
+     */
+    boolean isMetered;
+}
diff --git a/wifi/hostapd/aidl/android/hardware/wifi/hostapd/ParamSizeLimits.aidl b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/ParamSizeLimits.aidl
new file mode 100644
index 0000000..bf34c34
--- /dev/null
+++ b/wifi/hostapd/aidl/android/hardware/wifi/hostapd/ParamSizeLimits.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.hostapd;
+
+/**
+ * Size limits for some of the params used in this interface.
+ */
+@VintfStability
+@Backing(type="int")
+enum ParamSizeLimits {
+    /**
+     * Max length of SSID param.
+     */
+    SSID_MAX_LEN_IN_BYTES = 32,
+    /**
+     * Min length of PSK passphrase param.
+     */
+    WPA2_PSK_PASSPHRASE_MIN_LEN_IN_BYTES = 8,
+    /**
+     * Max length of PSK passphrase param.
+     */
+    WPA2_PSK_PASSPHRASE_MAX_LEN_IN_BYTES = 63,
+}
diff --git a/wifi/hostapd/aidl/vts/OWNERS b/wifi/hostapd/aidl/vts/OWNERS
new file mode 100644
index 0000000..2a7a7b0
--- /dev/null
+++ b/wifi/hostapd/aidl/vts/OWNERS
@@ -0,0 +1,2 @@
+etancohen@google.com
+lzye@google.com
diff --git a/wifi/hostapd/aidl/vts/functional/Android.bp b/wifi/hostapd/aidl/vts/functional/Android.bp
new file mode 100644
index 0000000..e58cf5e
--- /dev/null
+++ b/wifi/hostapd/aidl/vts/functional/Android.bp
@@ -0,0 +1,28 @@
+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: "VtsHalHostapdTargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    srcs: ["VtsHalHostapdTargetTest.cpp"],
+    shared_libs: [
+        "libbinder",
+        "libbinder_ndk",
+    ],
+    static_libs: [
+        "android.hardware.wifi.hostapd-V1-ndk",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
diff --git a/wifi/hostapd/aidl/vts/functional/VtsHalHostapdTargetTest.cpp b/wifi/hostapd/aidl/vts/functional/VtsHalHostapdTargetTest.cpp
new file mode 100644
index 0000000..8f88196
--- /dev/null
+++ b/wifi/hostapd/aidl/vts/functional/VtsHalHostapdTargetTest.cpp
@@ -0,0 +1,445 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <VtsCoreUtil.h>
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/wifi/hostapd/BnHostapd.h>
+#include <aidl/android/hardware/wifi/hostapd/BnHostapdCallback.h>
+#include <android/binder_manager.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+
+using aidl::android::hardware::wifi::hostapd::BandMask;
+using aidl::android::hardware::wifi::hostapd::BnHostapdCallback;
+using aidl::android::hardware::wifi::hostapd::ChannelParams;
+using aidl::android::hardware::wifi::hostapd::DebugLevel;
+using aidl::android::hardware::wifi::hostapd::EncryptionType;
+using aidl::android::hardware::wifi::hostapd::FrequencyRange;
+using aidl::android::hardware::wifi::hostapd::Ieee80211ReasonCode;
+using aidl::android::hardware::wifi::hostapd::IfaceParams;
+using aidl::android::hardware::wifi::hostapd::IHostapd;
+using aidl::android::hardware::wifi::hostapd::NetworkParams;
+using android::ProcessState;
+
+namespace {
+const unsigned char kNwSsid[] = {'t', 'e', 's', 't', '1', '2', '3', '4', '5'};
+const std::string kIfaceName = "wlan0";
+const std::string kPassphrase = "test12345";
+const std::string kInvalidMinPassphrase = "test";
+const std::string kInvalidMaxPassphrase =
+    "0123456789012345678901234567890123456789012345678901234567890123456789";
+const int kIfaceChannel = 6;
+const int kIfaceInvalidChannel = 567;
+const std::vector<uint8_t> kTestZeroMacAddr(6, 0x0);
+const Ieee80211ReasonCode kTestDisconnectReasonCode =
+    Ieee80211ReasonCode::WLAN_REASON_UNSPECIFIED;
+
+inline BandMask operator|(BandMask a, BandMask b) {
+    return static_cast<BandMask>(static_cast<int32_t>(a) |
+                                 static_cast<int32_t>(b));
+}
+}  // namespace
+
+class HostapdAidl : public testing::TestWithParam<std::string> {
+   public:
+    virtual void SetUp() override {
+        hostapd = IHostapd::fromBinder(ndk::SpAIBinder(
+            AServiceManager_waitForService(GetParam().c_str())));
+        ASSERT_NE(hostapd, nullptr);
+        EXPECT_TRUE(hostapd->setDebugParams(DebugLevel::EXCESSIVE).isOk());
+        isAcsSupport = testing::checkSubstringInCommandOutput(
+            "/system/bin/cmd wifi get-softap-supported-features",
+            "wifi_softap_acs_supported");
+        isWpa3SaeSupport = testing::checkSubstringInCommandOutput(
+            "/system/bin/cmd wifi get-softap-supported-features",
+            "wifi_softap_wpa3_sae_supported");
+        isBridgedSupport = testing::checkSubstringInCommandOutput(
+            "/system/bin/cmd wifi get-softap-supported-features",
+            "wifi_softap_bridged_ap_supported");
+    }
+
+    virtual void TearDown() override {
+        hostapd->terminate();
+        //  Wait 3 seconds to allow terminate to complete
+        sleep(3);
+    }
+
+    std::shared_ptr<IHostapd> hostapd;
+    bool isAcsSupport;
+    bool isWpa3SaeSupport;
+    bool isBridgedSupport;
+
+    IfaceParams getIfaceParamsWithoutAcs(std::string iface_name) {
+        IfaceParams iface_params;
+        ChannelParams channelParams;
+        std::vector<ChannelParams> vec_channelParams;
+
+        iface_params.name = iface_name;
+        iface_params.hwModeParams.enable80211N = true;
+        iface_params.hwModeParams.enable80211AC = false;
+        iface_params.hwModeParams.enable80211AX = false;
+        iface_params.hwModeParams.enable6GhzBand = false;
+
+        channelParams.enableAcs = false;
+        channelParams.acsShouldExcludeDfs = false;
+        channelParams.channel = kIfaceChannel;
+        channelParams.bandMask = BandMask::BAND_2_GHZ;
+
+        vec_channelParams.push_back(channelParams);
+        iface_params.channelParams = vec_channelParams;
+        return iface_params;
+    }
+
+    IfaceParams getIfaceParamsWithBridgedModeACS(std::string iface_name) {
+        IfaceParams iface_params = getIfaceParamsWithoutAcs(iface_name);
+        iface_params.channelParams[0].enableAcs = true;
+        iface_params.channelParams[0].acsShouldExcludeDfs = true;
+
+        std::vector<ChannelParams> vec_channelParams;
+        vec_channelParams.push_back(iface_params.channelParams[0]);
+
+        ChannelParams second_channelParams;
+        second_channelParams.channel = 0;
+        second_channelParams.enableAcs = true;
+        second_channelParams.bandMask = BandMask::BAND_5_GHZ;
+        vec_channelParams.push_back(second_channelParams);
+
+        iface_params.channelParams = vec_channelParams;
+        return iface_params;
+    }
+
+    IfaceParams getIfaceParamsWithAcs(std::string iface_name) {
+        IfaceParams iface_params = getIfaceParamsWithoutAcs(iface_name);
+        iface_params.channelParams[0].enableAcs = true;
+        iface_params.channelParams[0].acsShouldExcludeDfs = true;
+        iface_params.channelParams[0].channel = 0;
+        iface_params.channelParams[0].bandMask =
+            iface_params.channelParams[0].bandMask | BandMask::BAND_5_GHZ;
+        return iface_params;
+    }
+
+    IfaceParams getIfaceParamsWithAcsAndFreqRange(std::string iface_name) {
+        IfaceParams iface_params = getIfaceParamsWithAcs(iface_name);
+        FrequencyRange freqRange;
+        freqRange.startMhz = 2412;
+        freqRange.endMhz = 2462;
+        std::vector<FrequencyRange> vec_FrequencyRange;
+        vec_FrequencyRange.push_back(freqRange);
+        iface_params.channelParams[0].acsChannelFreqRangesMhz =
+            vec_FrequencyRange;
+        return iface_params;
+    }
+
+    IfaceParams getIfaceParamsWithAcsAndInvalidFreqRange(
+        std::string iface_name) {
+        IfaceParams iface_params =
+            getIfaceParamsWithAcsAndFreqRange(iface_name);
+        iface_params.channelParams[0].acsChannelFreqRangesMhz[0].startMhz =
+            222;
+        iface_params.channelParams[0].acsChannelFreqRangesMhz[0].endMhz =
+            999;
+        return iface_params;
+    }
+
+    IfaceParams getIfaceParamsWithInvalidChannel(std::string iface_name) {
+        IfaceParams iface_params = getIfaceParamsWithoutAcs(iface_name);
+        iface_params.channelParams[0].channel = kIfaceInvalidChannel;
+        return iface_params;
+    }
+
+    NetworkParams getOpenNwParams() {
+        NetworkParams nw_params;
+        nw_params.ssid =
+            std::vector<uint8_t>(kNwSsid, kNwSsid + sizeof(kNwSsid));
+        nw_params.isHidden = false;
+        nw_params.encryptionType = EncryptionType::NONE;
+        nw_params.isMetered = true;
+        return nw_params;
+    }
+
+    NetworkParams getPskNwParamsWithNonMetered() {
+        NetworkParams nw_params = getOpenNwParams();
+        nw_params.encryptionType = EncryptionType::WPA2;
+        nw_params.passphrase = kPassphrase;
+        nw_params.isMetered = false;
+        return nw_params;
+    }
+
+    NetworkParams getPskNwParams() {
+        NetworkParams nw_params = getOpenNwParams();
+        nw_params.encryptionType = EncryptionType::WPA2;
+        nw_params.passphrase = kPassphrase;
+        return nw_params;
+    }
+
+    NetworkParams getInvalidPskNwParams() {
+        NetworkParams nw_params = getOpenNwParams();
+        nw_params.encryptionType = EncryptionType::WPA2;
+        nw_params.passphrase = kInvalidMaxPassphrase;
+        return nw_params;
+    }
+
+    NetworkParams getSaeTransitionNwParams() {
+        NetworkParams nw_params = getOpenNwParams();
+        nw_params.encryptionType = EncryptionType::WPA3_SAE_TRANSITION;
+        nw_params.passphrase = kPassphrase;
+        return nw_params;
+    }
+
+    NetworkParams getInvalidSaeTransitionNwParams() {
+        NetworkParams nw_params = getOpenNwParams();
+        nw_params.encryptionType = EncryptionType::WPA2;
+        nw_params.passphrase = kInvalidMinPassphrase;
+        return nw_params;
+    }
+
+    NetworkParams getSaeNwParams() {
+        NetworkParams nw_params = getOpenNwParams();
+        nw_params.encryptionType = EncryptionType::WPA3_SAE;
+        nw_params.passphrase = kPassphrase;
+        return nw_params;
+    }
+
+    NetworkParams getInvalidSaeNwParams() {
+        NetworkParams nw_params = getOpenNwParams();
+        nw_params.encryptionType = EncryptionType::WPA3_SAE;
+        nw_params.passphrase = "";
+        return nw_params;
+    }
+};
+
+class HostapdCallback : public BnHostapdCallback {
+   public:
+    HostapdCallback() = default;
+    ::ndk::ScopedAStatus onApInstanceInfoChanged(
+        const ::aidl::android::hardware::wifi::hostapd::ApInfo &) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onConnectedClientsChanged(
+        const ::aidl::android::hardware::wifi::hostapd::ClientInfo &) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onFailure(const std::string &) override {
+        return ndk::ScopedAStatus::ok();
+    }
+};
+
+/**
+ * Register callback
+ */
+TEST_P(HostapdAidl, RegisterCallback) {
+    std::shared_ptr<HostapdCallback> callback =
+        ndk::SharedRefBase::make<HostapdCallback>();
+    ASSERT_NE(callback, nullptr);
+    EXPECT_TRUE(hostapd->registerCallback(callback).isOk());
+}
+
+/**
+ * Adds an access point with PSK network config & ACS enabled.
+ * Access point creation should pass.
+ */
+TEST_P(HostapdAidl, AddPskAccessPointWithAcs) {
+    if (!isAcsSupport) GTEST_SKIP() << "Missing ACS support";
+    auto status = hostapd->addAccessPoint(getIfaceParamsWithAcs(kIfaceName),
+                                          getPskNwParams());
+    EXPECT_TRUE(status.isOk());
+}
+
+/**
+ * Adds an access point with PSK network config, ACS enabled & frequency Range.
+ * Access point creation should pass.
+ */
+TEST_P(HostapdAidl, AddPskAccessPointWithAcsAndFreqRange) {
+    if (!isAcsSupport) GTEST_SKIP() << "Missing ACS support";
+    auto status = hostapd->addAccessPoint(
+        getIfaceParamsWithAcsAndFreqRange(kIfaceName), getPskNwParams());
+    EXPECT_TRUE(status.isOk());
+}
+
+/**
+ * Adds an access point with invalid channel range.
+ * Access point creation should fail.
+ */
+TEST_P(HostapdAidl, AddPskAccessPointWithAcsAndInvalidFreqRange) {
+    if (!isAcsSupport) GTEST_SKIP() << "Missing ACS support";
+    auto status = hostapd->addAccessPoint(
+        getIfaceParamsWithAcsAndInvalidFreqRange(kIfaceName), getPskNwParams());
+    EXPECT_FALSE(status.isOk());
+}
+
+/**
+ * Adds an access point with Open network config & ACS enabled.
+ * Access point creation should pass.
+ */
+TEST_P(HostapdAidl, AddOpenAccessPointWithAcs) {
+    if (!isAcsSupport) GTEST_SKIP() << "Missing ACS support";
+    auto status = hostapd->addAccessPoint(getIfaceParamsWithAcs(kIfaceName),
+                                          getOpenNwParams());
+    EXPECT_TRUE(status.isOk());
+}
+
+/**
+ * Adds an access point with PSK network config & ACS disabled.
+ * Access point creation should pass.
+ */
+TEST_P(HostapdAidl, AddPskAccessPointWithoutAcs) {
+    auto status = hostapd->addAccessPoint(getIfaceParamsWithoutAcs(kIfaceName),
+                                          getPskNwParams());
+    EXPECT_TRUE(status.isOk());
+}
+
+/**
+ * Adds an access point with PSK network config, ACS disabled & Non metered.
+ * Access point creation should pass.
+ */
+TEST_P(HostapdAidl, AddPskAccessPointWithoutAcsAndNonMetered) {
+    auto status = hostapd->addAccessPoint(getIfaceParamsWithoutAcs(kIfaceName),
+                                          getPskNwParamsWithNonMetered());
+    EXPECT_TRUE(status.isOk());
+}
+
+/**
+ * Adds an access point with Open network config & ACS disabled.
+ * Access point creation should pass.
+ */
+TEST_P(HostapdAidl, AddOpenAccessPointWithoutAcs) {
+    auto status = hostapd->addAccessPoint(getIfaceParamsWithoutAcs(kIfaceName),
+                                          getOpenNwParams());
+    EXPECT_TRUE(status.isOk());
+}
+
+/**
+ * Adds an access point with SAE Transition network config & ACS disabled.
+ * Access point creation should pass.
+ */
+TEST_P(HostapdAidl, AddSaeTransitionAccessPointWithoutAcs) {
+    if (!isWpa3SaeSupport) GTEST_SKIP() << "Missing SAE support";
+    auto status = hostapd->addAccessPoint(getIfaceParamsWithoutAcs(kIfaceName),
+                                          getSaeTransitionNwParams());
+    EXPECT_TRUE(status.isOk());
+}
+
+/**
+ * Adds an access point with SAE network config & ACS disabled.
+ * Access point creation should pass.
+ */
+TEST_P(HostapdAidl, AddSAEAccessPointWithoutAcs) {
+    if (!isWpa3SaeSupport) GTEST_SKIP() << "Missing SAE support";
+    auto status = hostapd->addAccessPoint(getIfaceParamsWithoutAcs(kIfaceName),
+                                          getSaeNwParams());
+    EXPECT_TRUE(status.isOk());
+}
+
+/**
+ * Adds & then removes an access point with PSK network config & ACS enabled.
+ * Access point creation & removal should pass.
+ */
+TEST_P(HostapdAidl, RemoveAccessPointWithAcs) {
+    if (!isAcsSupport) GTEST_SKIP() << "Missing ACS support";
+    auto status = hostapd->addAccessPoint(getIfaceParamsWithAcs(kIfaceName),
+                                          getPskNwParams());
+    EXPECT_TRUE(status.isOk());
+    EXPECT_TRUE(hostapd->removeAccessPoint(kIfaceName).isOk());
+}
+
+/**
+ * Adds & then removes an access point with PSK network config & ACS disabled.
+ * Access point creation & removal should pass.
+ */
+TEST_P(HostapdAidl, RemoveAccessPointWithoutAcs) {
+    auto status = hostapd->addAccessPoint(getIfaceParamsWithoutAcs(kIfaceName),
+                                          getPskNwParams());
+    EXPECT_TRUE(status.isOk());
+    EXPECT_TRUE(hostapd->removeAccessPoint(kIfaceName).isOk());
+}
+
+/**
+ * Adds an access point with invalid channel.
+ * Access point creation should fail.
+ */
+TEST_P(HostapdAidl, AddPskAccessPointWithInvalidChannel) {
+    auto status = hostapd->addAccessPoint(
+        getIfaceParamsWithInvalidChannel(kIfaceName), getPskNwParams());
+    EXPECT_FALSE(status.isOk());
+}
+
+/**
+ * Adds an access point with invalid PSK network config.
+ * Access point creation should fail.
+ */
+TEST_P(HostapdAidl, AddInvalidPskAccessPointWithoutAcs) {
+    auto status = hostapd->addAccessPoint(getIfaceParamsWithoutAcs(kIfaceName),
+                                          getInvalidPskNwParams());
+    EXPECT_FALSE(status.isOk());
+}
+
+/**
+ * Adds an access point with invalid SAE transition network config.
+ * Access point creation should fail.
+ */
+TEST_P(HostapdAidl, AddInvalidSaeTransitionAccessPointWithoutAcs) {
+    if (!isWpa3SaeSupport) GTEST_SKIP() << "Missing SAE support";
+    auto status = hostapd->addAccessPoint(getIfaceParamsWithoutAcs(kIfaceName),
+                                          getInvalidSaeTransitionNwParams());
+    EXPECT_FALSE(status.isOk());
+}
+
+/**
+ * Adds an access point with invalid SAE network config.
+ * Access point creation should fail.
+ */
+TEST_P(HostapdAidl, AddInvalidSaeAccessPointWithoutAcs) {
+    if (!isWpa3SaeSupport) GTEST_SKIP() << "Missing SAE support";
+    auto status = hostapd->addAccessPoint(getIfaceParamsWithoutAcs(kIfaceName),
+                                          getInvalidSaeNwParams());
+    EXPECT_FALSE(status.isOk());
+}
+
+/**
+ * forceClientDisconnect should fail when hotspot interface available.
+ */
+TEST_P(HostapdAidl, DisconnectClientWhenIfacAvailable) {
+    auto status = hostapd->addAccessPoint(getIfaceParamsWithoutAcs(kIfaceName),
+                                          getOpenNwParams());
+    EXPECT_TRUE(status.isOk());
+
+    status = hostapd->forceClientDisconnect(kIfaceName, kTestZeroMacAddr,
+                                            kTestDisconnectReasonCode);
+    EXPECT_FALSE(status.isOk());
+}
+
+/**
+ * AddAccessPointWithDualBandConfig should pass
+ */
+TEST_P(HostapdAidl, AddAccessPointWithDualBandConfig) {
+    if (!isBridgedSupport) GTEST_SKIP() << "Missing Bridged AP support";
+    auto status = hostapd->addAccessPoint(
+        getIfaceParamsWithBridgedModeACS(kIfaceName), getOpenNwParams());
+    EXPECT_TRUE(status.isOk());
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HostapdAidl);
+INSTANTIATE_TEST_SUITE_P(
+    Hostapd, HostapdAidl,
+    testing::ValuesIn(android::getAidlHalInstanceNames(IHostapd::descriptor)),
+    android::PrintInstanceNameToString);
+
+int main(int argc, char **argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    ProcessState::self()->setThreadPoolMaxThreadCount(1);
+    ProcessState::self()->startThreadPool();
+    return RUN_ALL_TESTS();
+}
diff --git a/wifi/offload/1.0/vts/OWNERS b/wifi/offload/1.0/vts/OWNERS
new file mode 100644
index 0000000..287152d
--- /dev/null
+++ b/wifi/offload/1.0/vts/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 33618
+arabawy@google.com
+etancohen@google.com
diff --git a/wifi/supplicant/1.0/vts/OWNERS b/wifi/supplicant/1.0/vts/OWNERS
new file mode 100644
index 0000000..b16dc11
--- /dev/null
+++ b/wifi/supplicant/1.0/vts/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 33618
+include ../../1.3/vts/OWNERS
diff --git a/wifi/supplicant/1.0/vts/functional/Android.bp b/wifi/supplicant/1.0/vts/functional/Android.bp
index 121117c..2d86822 100644
--- a/wifi/supplicant/1.0/vts/functional/Android.bp
+++ b/wifi/supplicant/1.0/vts/functional/Android.bp
@@ -44,6 +44,9 @@
 cc_test {
     name: "VtsHalWifiSupplicantV1_0TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: [
+        "supplicant_sta_network_hidl_test.cpp",
+    ],
     srcs: [
         "supplicant_hidl_test.cpp",
         "supplicant_sta_iface_hidl_test.cpp",
@@ -71,6 +74,9 @@
 cc_test {
     name: "VtsHalWifiSupplicantP2pV1_0TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
+    tidy_timeout_srcs: [
+        "supplicant_p2p_iface_hidl_test.cpp",
+    ],
     srcs: [
         "VtsHalWifiSupplicantP2pV1_0TargetTest.cpp",
         "supplicant_p2p_iface_hidl_test.cpp",
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
index 114fe4f..086166a 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
@@ -69,37 +69,6 @@
 // disable.
 bool waitForSupplicantStop() { return waitForSupplicantState(false); }
 
-// Helper function to initialize the driver and firmware to STA mode
-// using the vendor HAL HIDL interface.
-void initilializeDriverAndFirmware(const std::string& wifi_instance_name) {
-    // Skip if wifi instance is not set.
-    if (wifi_instance_name == "") {
-        return;
-    }
-    if (getWifi(wifi_instance_name) != nullptr) {
-        sp<IWifiChip> wifi_chip = getWifiChip(wifi_instance_name);
-        ChipModeId mode_id;
-        EXPECT_TRUE(configureChipToSupportIfaceType(
-            wifi_chip, ::android::hardware::wifi::V1_0::IfaceType::STA, &mode_id));
-    } else {
-        LOG(WARNING) << __func__ << ": Vendor HAL not supported";
-    }
-}
-
-// Helper function to deinitialize the driver and firmware
-// using the vendor HAL HIDL interface.
-void deInitilializeDriverAndFirmware(const std::string& wifi_instance_name) {
-    // Skip if wifi instance is not set.
-    if (wifi_instance_name == "") {
-        return;
-    }
-    if (getWifi(wifi_instance_name) != nullptr) {
-        stopWifi(wifi_instance_name);
-    } else {
-        LOG(WARNING) << __func__ << ": Vendor HAL not supported";
-    }
-}
-
 // Helper function to find any iface of the desired type exposed.
 bool findIfaceOfType(sp<ISupplicant> supplicant, IfaceType desired_type,
                      ISupplicant::IfaceInfo* out_info) {
@@ -156,14 +125,46 @@
     SupplicantManager supplicant_manager;
 
     ASSERT_TRUE(supplicant_manager.StopSupplicant());
-    deInitilializeDriverAndFirmware(wifi_instance_name);
+    deInitializeDriverAndFirmware(wifi_instance_name);
     ASSERT_FALSE(supplicant_manager.IsSupplicantRunning());
 }
 
+// Helper function to initialize the driver and firmware to STA mode
+// using the vendor HAL HIDL interface.
+void initializeDriverAndFirmware(const std::string& wifi_instance_name) {
+    // Skip if wifi instance is not set.
+    if (wifi_instance_name == "") {
+        return;
+    }
+    if (getWifi(wifi_instance_name) != nullptr) {
+        sp<IWifiChip> wifi_chip = getWifiChip(wifi_instance_name);
+        ChipModeId mode_id;
+        EXPECT_TRUE(configureChipToSupportIfaceType(
+            wifi_chip, ::android::hardware::wifi::V1_0::IfaceType::STA,
+            &mode_id));
+    } else {
+        LOG(WARNING) << __func__ << ": Vendor HAL not supported";
+    }
+}
+
+// Helper function to deinitialize the driver and firmware
+// using the vendor HAL HIDL interface.
+void deInitializeDriverAndFirmware(const std::string& wifi_instance_name) {
+    // Skip if wifi instance is not set.
+    if (wifi_instance_name == "") {
+        return;
+    }
+    if (getWifi(wifi_instance_name) != nullptr) {
+        stopWifi(wifi_instance_name);
+    } else {
+        LOG(WARNING) << __func__ << ": Vendor HAL not supported";
+    }
+}
+
 void startSupplicantAndWaitForHidlService(
     const std::string& wifi_instance_name,
     const std::string& supplicant_instance_name) {
-    initilializeDriverAndFirmware(wifi_instance_name);
+    initializeDriverAndFirmware(wifi_instance_name);
 
     SupplicantManager supplicant_manager;
     ASSERT_TRUE(supplicant_manager.StartSupplicant());
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.h b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.h
index 22cea8c..7228623 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.h
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.h
@@ -42,6 +42,11 @@
     const std::string& wifi_instance_name,
     const std::string& supplicant_instance_name);
 
+// Used to initialize/deinitialize the driver and firmware at the
+// beginning and end of each test.
+void initializeDriverAndFirmware(const std::string& wifi_instance_name);
+void deInitializeDriverAndFirmware(const std::string& wifi_instance_name);
+
 // Helper functions to obtain references to the various HIDL interface objects.
 // Note: We only have a single instance of each of these objects currently.
 // These helper functions should be modified to return vectors if we support
diff --git a/wifi/supplicant/1.1/vts/OWNERS b/wifi/supplicant/1.1/vts/OWNERS
new file mode 100644
index 0000000..b16dc11
--- /dev/null
+++ b/wifi/supplicant/1.1/vts/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 33618
+include ../../1.3/vts/OWNERS
diff --git a/wifi/supplicant/1.2/vts/OWNERS b/wifi/supplicant/1.2/vts/OWNERS
index cf81c79..b16dc11 100644
--- a/wifi/supplicant/1.2/vts/OWNERS
+++ b/wifi/supplicant/1.2/vts/OWNERS
@@ -1,2 +1,2 @@
-arabawy@google.com
-etancohen@google.com
+# Bug component: 33618
+include ../../1.3/vts/OWNERS
diff --git a/wifi/supplicant/1.3/vts/OWNERS b/wifi/supplicant/1.3/vts/OWNERS
deleted file mode 100644
index cf81c79..0000000
--- a/wifi/supplicant/1.3/vts/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-arabawy@google.com
-etancohen@google.com
diff --git a/wifi/supplicant/1.4/vts/OWNERS b/wifi/supplicant/1.4/vts/OWNERS
index cf81c79..b16dc11 100644
--- a/wifi/supplicant/1.4/vts/OWNERS
+++ b/wifi/supplicant/1.4/vts/OWNERS
@@ -1,2 +1,2 @@
-arabawy@google.com
-etancohen@google.com
+# Bug component: 33618
+include ../../1.3/vts/OWNERS
diff --git a/wifi/supplicant/1.4/vts/functional/supplicant_p2p_iface_hidl_test.cpp b/wifi/supplicant/1.4/vts/functional/supplicant_p2p_iface_hidl_test.cpp
index 4427c390..d68520a 100644
--- a/wifi/supplicant/1.4/vts/functional/supplicant_p2p_iface_hidl_test.cpp
+++ b/wifi/supplicant/1.4/vts/functional/supplicant_p2p_iface_hidl_test.cpp
@@ -49,6 +49,9 @@
    public:
     virtual void SetUp() override {
         SupplicantHidlTestBaseV1_4::SetUp();
+        if (!isP2pOn_) {
+            GTEST_SKIP() << "Wi-Fi Direct is not supported, skip this test.";
+        }
         p2p_iface_ = getSupplicantP2pIface_1_4(supplicant_);
         ASSERT_NE(p2p_iface_.get(), nullptr);
     }
diff --git a/wifi/supplicant/OWNERS b/wifi/supplicant/OWNERS
new file mode 100644
index 0000000..7febd60
--- /dev/null
+++ b/wifi/supplicant/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 33618
+arabawy@google.com
+etancohen@google.com
+gbiren@google.com
+lzye@google.com
diff --git a/wifi/supplicant/aidl/Android.bp b/wifi/supplicant/aidl/Android.bp
new file mode 100644
index 0000000..d00dd21
--- /dev/null
+++ b/wifi/supplicant/aidl/Android.bp
@@ -0,0 +1,46 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+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.supplicant",
+    vendor_available: true,
+    srcs: [
+        "android/hardware/wifi/supplicant/*.aidl",
+    ],
+    stability: "vintf",
+    backend: {
+        java: {
+            sdk_version: "module_current",
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.wifi",
+            ],
+            min_sdk_version: "30",
+        },
+        ndk: {
+            vndk: {
+                enabled: true,
+            },
+        },
+    },
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/AnqpData.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/AnqpData.aidl
new file mode 100644
index 0000000..d8e49d7
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/AnqpData.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+parcelable AnqpData {
+  byte[] venueName;
+  byte[] roamingConsortium;
+  byte[] ipAddrTypeAvailability;
+  byte[] naiRealm;
+  byte[] anqp3gppCellularNetwork;
+  byte[] domainName;
+  byte[] venueUrl;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/AnqpInfoId.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/AnqpInfoId.aidl
new file mode 100644
index 0000000..cc32360
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/AnqpInfoId.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum AnqpInfoId {
+  VENUE_NAME = 258,
+  ROAMING_CONSORTIUM = 261,
+  IP_ADDR_TYPE_AVAILABILITY = 262,
+  NAI_REALM = 263,
+  ANQP_3GPP_CELLULAR_NETWORK = 264,
+  DOMAIN_NAME = 268,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/AssociationRejectionData.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/AssociationRejectionData.aidl
new file mode 100644
index 0000000..f6830dc
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/AssociationRejectionData.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+parcelable AssociationRejectionData {
+  byte[] ssid;
+  byte[] bssid;
+  android.hardware.wifi.supplicant.StaIfaceStatusCode statusCode;
+  boolean timedOut;
+  boolean isMboAssocDisallowedReasonCodePresent;
+  android.hardware.wifi.supplicant.MboAssocDisallowedReasonCode mboAssocDisallowedReason;
+  boolean isOceRssiBasedAssocRejectAttrPresent;
+  android.hardware.wifi.supplicant.OceRssiBasedAssocRejectAttr oceRssiBasedAssocRejectData;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/AuthAlgMask.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/AuthAlgMask.aidl
new file mode 100644
index 0000000..9cd178d
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/AuthAlgMask.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum AuthAlgMask {
+  OPEN = 1,
+  SHARED = 2,
+  LEAP = 4,
+  SAE = 16,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/BssTmData.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/BssTmData.aidl
new file mode 100644
index 0000000..34d894d
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/BssTmData.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+parcelable BssTmData {
+  android.hardware.wifi.supplicant.BssTmStatusCode status;
+  android.hardware.wifi.supplicant.BssTmDataFlagsMask flags;
+  int assocRetryDelayMs;
+  android.hardware.wifi.supplicant.MboTransitionReasonCode mboTransitionReason;
+  android.hardware.wifi.supplicant.MboCellularDataConnectionPrefValue mboCellPreference;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/BssTmDataFlagsMask.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/BssTmDataFlagsMask.aidl
new file mode 100644
index 0000000..f215f05
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/BssTmDataFlagsMask.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum BssTmDataFlagsMask {
+  WNM_MODE_PREFERRED_CANDIDATE_LIST_INCLUDED = 1,
+  WNM_MODE_ABRIDGED = 2,
+  WNM_MODE_DISASSOCIATION_IMMINENT = 4,
+  WNM_MODE_BSS_TERMINATION_INCLUDED = 8,
+  WNM_MODE_ESS_DISASSOCIATION_IMMINENT = 16,
+  MBO_TRANSITION_REASON_CODE_INCLUDED = 32,
+  MBO_ASSOC_RETRY_DELAY_INCLUDED = 64,
+  MBO_CELLULAR_DATA_CONNECTION_PREFERENCE_INCLUDED = 128,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/BssTmStatusCode.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/BssTmStatusCode.aidl
new file mode 100644
index 0000000..c95825f
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/BssTmStatusCode.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="byte") @VintfStability
+enum BssTmStatusCode {
+  ACCEPT = 0,
+  REJECT_UNSPECIFIED = 1,
+  REJECT_INSUFFICIENT_BEACON = 2,
+  REJECT_INSUFFICIENT_CAPABITY = 3,
+  REJECT_BSS_TERMINATION_UNDESIRED = 4,
+  REJECT_BSS_TERMINATION_DELAY_REQUEST = 5,
+  REJECT_STA_CANDIDATE_LIST_PROVIDED = 6,
+  REJECT_NO_SUITABLE_CANDIDATES = 7,
+  REJECT_LEAVING_ESS = 8,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/BssidChangeReason.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/BssidChangeReason.aidl
new file mode 100644
index 0000000..1d24579
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/BssidChangeReason.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="byte") @VintfStability
+enum BssidChangeReason {
+  ASSOC_START = 0,
+  ASSOC_COMPLETE = 1,
+  DISASSOC = 2,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/BtCoexistenceMode.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/BtCoexistenceMode.aidl
new file mode 100644
index 0000000..bdc1b4a
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/BtCoexistenceMode.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="byte") @VintfStability
+enum BtCoexistenceMode {
+  ENABLED = 0,
+  DISABLED = 1,
+  SENSE = 2,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ConnectionCapabilities.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ConnectionCapabilities.aidl
new file mode 100644
index 0000000..433b3d80
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ConnectionCapabilities.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+parcelable ConnectionCapabilities {
+  android.hardware.wifi.supplicant.WifiTechnology technology;
+  int channelBandwidth;
+  int maxNumberTxSpatialStreams;
+  int maxNumberRxSpatialStreams;
+  android.hardware.wifi.supplicant.LegacyMode legacyMode;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DebugLevel.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DebugLevel.aidl
new file mode 100644
index 0000000..fbfb5b3
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DebugLevel.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum DebugLevel {
+  EXCESSIVE = 0,
+  MSGDUMP = 1,
+  DEBUG = 2,
+  INFO = 3,
+  WARNING = 4,
+  ERROR = 5,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppAkm.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppAkm.aidl
new file mode 100644
index 0000000..df2aef8
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppAkm.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum DppAkm {
+  PSK = 0,
+  PSK_SAE = 1,
+  SAE = 2,
+  DPP = 3,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppCurve.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppCurve.aidl
new file mode 100644
index 0000000..e69da44
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppCurve.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum DppCurve {
+  PRIME256V1 = 0,
+  SECP384R1 = 1,
+  SECP521R1 = 2,
+  BRAINPOOLP256R1 = 3,
+  BRAINPOOLP384R1 = 4,
+  BRAINPOOLP512R1 = 5,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppEventType.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppEventType.aidl
new file mode 100644
index 0000000..9e394fc
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppEventType.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum DppEventType {
+  CONFIGURATION_SENT = 0,
+  CONFIGURATION_APPLIED = 1,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppFailureCode.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppFailureCode.aidl
new file mode 100644
index 0000000..7e7c806
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppFailureCode.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum DppFailureCode {
+  INVALID_URI = 0,
+  AUTHENTICATION = 1,
+  NOT_COMPATIBLE = 2,
+  CONFIGURATION = 3,
+  BUSY = 4,
+  TIMEOUT = 5,
+  FAILURE = 6,
+  NOT_SUPPORTED = 7,
+  CONFIGURATION_REJECTED = 8,
+  CANNOT_FIND_NETWORK = 9,
+  ENROLLEE_AUTHENTICATION = 10,
+  URI_GENERATION = 11,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppNetRole.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppNetRole.aidl
new file mode 100644
index 0000000..c6d3522
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppNetRole.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum DppNetRole {
+  STA = 0,
+  AP = 1,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppProgressCode.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppProgressCode.aidl
new file mode 100644
index 0000000..f0618a5
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppProgressCode.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum DppProgressCode {
+  AUTHENTICATION_SUCCESS = 0,
+  RESPONSE_PENDING = 1,
+  CONFIGURATION_SENT_WAITING_RESPONSE = 2,
+  CONFIGURATION_ACCEPTED = 3,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppResponderBootstrapInfo.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppResponderBootstrapInfo.aidl
new file mode 100644
index 0000000..8b6492b
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/DppResponderBootstrapInfo.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+parcelable DppResponderBootstrapInfo {
+  int bootstrapId;
+  int listenChannel;
+  String uri;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/EapErrorCode.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/EapErrorCode.aidl
new file mode 100644
index 0000000..2cf81d9
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/EapErrorCode.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum EapErrorCode {
+  SIM_GENERAL_FAILURE_AFTER_AUTH = 0,
+  SIM_TEMPORARILY_DENIED = 1026,
+  SIM_NOT_SUBSCRIBED = 1031,
+  SIM_GENERAL_FAILURE_BEFORE_AUTH = 16384,
+  SIM_VENDOR_SPECIFIC_EXPIRED_CERT = 16385,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/EapMethod.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/EapMethod.aidl
new file mode 100644
index 0000000..4ab23af
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/EapMethod.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum EapMethod {
+  PEAP = 0,
+  TLS = 1,
+  TTLS = 2,
+  PWD = 3,
+  SIM = 4,
+  AKA = 5,
+  AKA_PRIME = 6,
+  WFA_UNAUTH_TLS = 7,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/EapPhase2Method.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/EapPhase2Method.aidl
new file mode 100644
index 0000000..4bd93a0
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/EapPhase2Method.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum EapPhase2Method {
+  NONE = 0,
+  PAP = 1,
+  MSPAP = 2,
+  MSPAPV2 = 3,
+  GTC = 4,
+  SIM = 5,
+  AKA = 6,
+  AKA_PRIME = 7,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ExtRadioWorkDefaults.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ExtRadioWorkDefaults.aidl
new file mode 100644
index 0000000..cbf1a3e
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ExtRadioWorkDefaults.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum ExtRadioWorkDefaults {
+  TIMEOUT_IN_SECS = 10,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/FreqRange.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/FreqRange.aidl
new file mode 100644
index 0000000..0971d51
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/FreqRange.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+parcelable FreqRange {
+  int min;
+  int max;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/GroupCipherMask.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/GroupCipherMask.aidl
new file mode 100644
index 0000000..f2da925
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/GroupCipherMask.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum GroupCipherMask {
+  WEP40 = 2,
+  WEP104 = 4,
+  TKIP = 8,
+  CCMP = 16,
+  GTK_NOT_USED = 16384,
+  GCMP_256 = 256,
+  SMS4 = 128,
+  GCMP_128 = 64,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/GroupMgmtCipherMask.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/GroupMgmtCipherMask.aidl
new file mode 100644
index 0000000..c24d6cc
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/GroupMgmtCipherMask.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum GroupMgmtCipherMask {
+  BIP_GMAC_128 = 2048,
+  BIP_GMAC_256 = 4096,
+  BIP_CMAC_256 = 8192,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/GsmRand.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/GsmRand.aidl
new file mode 100644
index 0000000..599a683
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/GsmRand.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+parcelable GsmRand {
+  byte[] data;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/Hs20AnqpData.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/Hs20AnqpData.aidl
new file mode 100644
index 0000000..43b182a
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/Hs20AnqpData.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+parcelable Hs20AnqpData {
+  byte[] operatorFriendlyName;
+  byte[] wanMetrics;
+  byte[] connectionCapability;
+  byte[] osuProvidersList;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/Hs20AnqpSubtypes.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/Hs20AnqpSubtypes.aidl
new file mode 100644
index 0000000..270d43b
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/Hs20AnqpSubtypes.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum Hs20AnqpSubtypes {
+  OPERATOR_FRIENDLY_NAME = 3,
+  WAN_METRICS = 4,
+  CONNECTION_CAPABILITY = 5,
+  OSU_PROVIDERS_LIST = 8,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicant.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicant.aidl
new file mode 100644
index 0000000..4b26ac3
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicant.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+interface ISupplicant {
+  @PropagateAllowBlocking android.hardware.wifi.supplicant.ISupplicantP2pIface addP2pInterface(in String ifName);
+  @PropagateAllowBlocking android.hardware.wifi.supplicant.ISupplicantStaIface addStaInterface(in String ifName);
+  android.hardware.wifi.supplicant.DebugLevel getDebugLevel();
+  @PropagateAllowBlocking android.hardware.wifi.supplicant.ISupplicantP2pIface getP2pInterface(in String ifName);
+  @PropagateAllowBlocking android.hardware.wifi.supplicant.ISupplicantStaIface getStaInterface(in String ifName);
+  boolean isDebugShowKeysEnabled();
+  boolean isDebugShowTimestampEnabled();
+  android.hardware.wifi.supplicant.IfaceInfo[] listInterfaces();
+  void registerCallback(in android.hardware.wifi.supplicant.ISupplicantCallback callback);
+  void removeInterface(in android.hardware.wifi.supplicant.IfaceInfo ifaceInfo);
+  void setConcurrencyPriority(in android.hardware.wifi.supplicant.IfaceType type);
+  void setDebugParams(in android.hardware.wifi.supplicant.DebugLevel level, in boolean showTimestamp, in boolean showKeys);
+  oneway void terminate();
+  const int EXT_RADIO_WORK_TIMEOUT_IN_SECS = 10;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantCallback.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantCallback.aidl
new file mode 100644
index 0000000..72ab3b9
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantCallback.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+interface ISupplicantCallback {
+  oneway void onInterfaceCreated(in String ifaceName);
+  oneway void onInterfaceRemoved(in String ifaceName);
+  oneway void onTerminating();
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pIface.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pIface.aidl
new file mode 100644
index 0000000..7876d86
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pIface.aidl
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+interface ISupplicantP2pIface {
+  void addBonjourService(in byte[] query, in byte[] response);
+  void addGroup(in boolean persistent, in int persistentNetworkId);
+  void addGroupWithConfig(in byte[] ssid, in String pskPassphrase, in boolean persistent, in int freq, in byte[] peerAddress, in boolean joinExistingGroup);
+  @PropagateAllowBlocking android.hardware.wifi.supplicant.ISupplicantP2pNetwork addNetwork();
+  void addUpnpService(in int version, in String serviceName);
+  void cancelConnect();
+  void cancelServiceDiscovery(in long identifier);
+  void cancelWps(in String groupIfName);
+  void configureExtListen(in int periodInMillis, in int intervalInMillis);
+  String connect(in byte[] peerAddress, in android.hardware.wifi.supplicant.WpsProvisionMethod provisionMethod, in String preSelectedPin, in boolean joinExistingGroup, in boolean persistent, in int goIntent);
+  byte[] createNfcHandoverRequestMessage();
+  byte[] createNfcHandoverSelectMessage();
+  void enableWfd(in boolean enable);
+  void find(in int timeoutInSec);
+  void flush();
+  void flushServices();
+  byte[] getDeviceAddress();
+  boolean getEdmg();
+  android.hardware.wifi.supplicant.P2pGroupCapabilityMask getGroupCapability(in byte[] peerAddress);
+  String getName();
+  @PropagateAllowBlocking android.hardware.wifi.supplicant.ISupplicantP2pNetwork getNetwork(in int id);
+  byte[] getSsid(in byte[] peerAddress);
+  android.hardware.wifi.supplicant.IfaceType getType();
+  void invite(in String groupIfName, in byte[] goDeviceAddress, in byte[] peerAddress);
+  int[] listNetworks();
+  void provisionDiscovery(in byte[] peerAddress, in android.hardware.wifi.supplicant.WpsProvisionMethod provisionMethod);
+  void registerCallback(in android.hardware.wifi.supplicant.ISupplicantP2pIfaceCallback callback);
+  void reinvoke(in int persistentNetworkId, in byte[] peerAddress);
+  void reject(in byte[] peerAddress);
+  void removeBonjourService(in byte[] query);
+  void removeGroup(in String groupIfName);
+  void removeNetwork(in int id);
+  void removeUpnpService(in int version, in String serviceName);
+  void reportNfcHandoverInitiation(in byte[] select);
+  void reportNfcHandoverResponse(in byte[] request);
+  long requestServiceDiscovery(in byte[] peerAddress, in byte[] query);
+  void saveConfig();
+  void setDisallowedFrequencies(in android.hardware.wifi.supplicant.FreqRange[] ranges);
+  void setEdmg(in boolean enable);
+  void setGroupIdle(in String groupIfName, in int timeoutInSec);
+  void setListenChannel(in int channel, in int operatingClass);
+  void setMacRandomization(in boolean enable);
+  void setMiracastMode(in android.hardware.wifi.supplicant.MiracastMode mode);
+  void setPowerSave(in String groupIfName, in boolean enable);
+  void setSsidPostfix(in byte[] postfix);
+  void setWfdDeviceInfo(in byte[] info);
+  void setWfdR2DeviceInfo(in byte[] info);
+  void setWpsConfigMethods(in android.hardware.wifi.supplicant.WpsConfigMethods configMethods);
+  void setWpsDeviceName(in String name);
+  void setWpsDeviceType(in byte[] type);
+  void setWpsManufacturer(in String manufacturer);
+  void setWpsModelName(in String modelName);
+  void setWpsModelNumber(in String modelNumber);
+  void setWpsSerialNumber(in String serialNumber);
+  void startWpsPbc(in String groupIfName, in byte[] bssid);
+  String startWpsPinDisplay(in String groupIfName, in byte[] bssid);
+  void startWpsPinKeypad(in String groupIfName, in String pin);
+  void stopFind();
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pIfaceCallback.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pIfaceCallback.aidl
new file mode 100644
index 0000000..ed435e2
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pIfaceCallback.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+interface ISupplicantP2pIfaceCallback {
+  oneway void onDeviceFound(in byte[] srcAddress, in byte[] p2pDeviceAddress, in byte[] primaryDeviceType, in String deviceName, in android.hardware.wifi.supplicant.WpsConfigMethods configMethods, in byte deviceCapabilities, in android.hardware.wifi.supplicant.P2pGroupCapabilityMask groupCapabilities, in byte[] wfdDeviceInfo);
+  oneway void onDeviceLost(in byte[] p2pDeviceAddress);
+  oneway void onFindStopped();
+  oneway void onGoNegotiationCompleted(in android.hardware.wifi.supplicant.P2pStatusCode status);
+  oneway void onGoNegotiationRequest(in byte[] srcAddress, in android.hardware.wifi.supplicant.WpsDevPasswordId passwordId);
+  oneway void onGroupFormationFailure(in String failureReason);
+  oneway void onGroupFormationSuccess();
+  oneway void onGroupRemoved(in String groupIfname, in boolean isGroupOwner);
+  oneway void onGroupStarted(in String groupIfname, in boolean isGroupOwner, in byte[] ssid, in int frequency, in byte[] psk, in String passphrase, in byte[] goDeviceAddress, in boolean isPersistent);
+  oneway void onInvitationReceived(in byte[] srcAddress, in byte[] goDeviceAddress, in byte[] bssid, in int persistentNetworkId, in int operatingFrequency);
+  oneway void onInvitationResult(in byte[] bssid, in android.hardware.wifi.supplicant.P2pStatusCode status);
+  oneway void onProvisionDiscoveryCompleted(in byte[] p2pDeviceAddress, in boolean isRequest, in android.hardware.wifi.supplicant.P2pProvDiscStatusCode status, in android.hardware.wifi.supplicant.WpsConfigMethods configMethods, in String generatedPin);
+  oneway void onR2DeviceFound(in byte[] srcAddress, in byte[] p2pDeviceAddress, in byte[] primaryDeviceType, in String deviceName, in android.hardware.wifi.supplicant.WpsConfigMethods configMethods, in byte deviceCapabilities, in android.hardware.wifi.supplicant.P2pGroupCapabilityMask groupCapabilities, in byte[] wfdDeviceInfo, in byte[] wfdR2DeviceInfo);
+  oneway void onServiceDiscoveryResponse(in byte[] srcAddress, in char updateIndicator, in byte[] tlvs);
+  oneway void onStaAuthorized(in byte[] srcAddress, in byte[] p2pDeviceAddress);
+  oneway void onStaDeauthorized(in byte[] srcAddress, in byte[] p2pDeviceAddress);
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pNetwork.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pNetwork.aidl
new file mode 100644
index 0000000..ef72724
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantP2pNetwork.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+interface ISupplicantP2pNetwork {
+  byte[] getBssid();
+  android.hardware.wifi.supplicant.MacAddress[] getClientList();
+  int getId();
+  String getInterfaceName();
+  byte[] getSsid();
+  android.hardware.wifi.supplicant.IfaceType getType();
+  boolean isCurrent();
+  boolean isGroupOwner();
+  boolean isPersistent();
+  void setClientList(in android.hardware.wifi.supplicant.MacAddress[] clients);
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl
new file mode 100644
index 0000000..20c52ac
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+interface ISupplicantStaIface {
+  int addDppPeerUri(in String uri);
+  int addExtRadioWork(in String name, in int freqInMhz, in int timeoutInSec);
+  @PropagateAllowBlocking android.hardware.wifi.supplicant.ISupplicantStaNetwork addNetwork();
+  void addRxFilter(in android.hardware.wifi.supplicant.RxFilterType type);
+  void cancelWps();
+  void disconnect();
+  void enableAutoReconnect(in boolean enable);
+  void filsHlpAddRequest(in byte[] dst_mac, in byte[] pkt);
+  void filsHlpFlushRequest();
+  android.hardware.wifi.supplicant.DppResponderBootstrapInfo generateDppBootstrapInfoForResponder(in byte[] macAddress, in String deviceInfo, in android.hardware.wifi.supplicant.DppCurve curve);
+  android.hardware.wifi.supplicant.ConnectionCapabilities getConnectionCapabilities();
+  android.hardware.wifi.supplicant.KeyMgmtMask getKeyMgmtCapabilities();
+  byte[] getMacAddress();
+  String getName();
+  @PropagateAllowBlocking android.hardware.wifi.supplicant.ISupplicantStaNetwork getNetwork(in int id);
+  android.hardware.wifi.supplicant.IfaceType getType();
+  android.hardware.wifi.supplicant.WpaDriverCapabilitiesMask getWpaDriverCapabilities();
+  void initiateAnqpQuery(in byte[] macAddress, in android.hardware.wifi.supplicant.AnqpInfoId[] infoElements, in android.hardware.wifi.supplicant.Hs20AnqpSubtypes[] subTypes);
+  void initiateHs20IconQuery(in byte[] macAddress, in String fileName);
+  void initiateTdlsDiscover(in byte[] macAddress);
+  void initiateTdlsSetup(in byte[] macAddress);
+  void initiateTdlsTeardown(in byte[] macAddress);
+  void initiateVenueUrlAnqpQuery(in byte[] macAddress);
+  int[] listNetworks();
+  void reassociate();
+  void reconnect();
+  void registerCallback(in android.hardware.wifi.supplicant.ISupplicantStaIfaceCallback callback);
+  void removeDppUri(in int id);
+  void removeExtRadioWork(in int id);
+  void removeNetwork(in int id);
+  void removeRxFilter(in android.hardware.wifi.supplicant.RxFilterType type);
+  void setBtCoexistenceMode(in android.hardware.wifi.supplicant.BtCoexistenceMode mode);
+  void setBtCoexistenceScanModeEnabled(in boolean enable);
+  void setCountryCode(in byte[] code);
+  void setExternalSim(in boolean useExternalSim);
+  void setMboCellularDataStatus(in boolean available);
+  void setPowerSave(in boolean enable);
+  void setSuspendModeEnabled(in boolean enable);
+  void setWpsConfigMethods(in android.hardware.wifi.supplicant.WpsConfigMethods configMethods);
+  void setWpsDeviceName(in String name);
+  void setWpsDeviceType(in byte[] type);
+  void setWpsManufacturer(in String manufacturer);
+  void setWpsModelName(in String modelName);
+  void setWpsModelNumber(in String modelNumber);
+  void setWpsSerialNumber(in String serialNumber);
+  void startDppConfiguratorInitiator(in int peerBootstrapId, in int ownBootstrapId, in String ssid, in String password, in String psk, in android.hardware.wifi.supplicant.DppNetRole netRole, in android.hardware.wifi.supplicant.DppAkm securityAkm);
+  void startDppEnrolleeInitiator(in int peerBootstrapId, in int ownBootstrapId);
+  void startDppEnrolleeResponder(in int listenChannel);
+  void startRxFilter();
+  void startWpsPbc(in byte[] bssid);
+  String startWpsPinDisplay(in byte[] bssid);
+  void startWpsPinKeypad(in String pin);
+  void startWpsRegistrar(in byte[] bssid, in String pin);
+  void stopDppInitiator();
+  void stopDppResponder(in int ownBootstrapId);
+  void stopRxFilter();
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
new file mode 100644
index 0000000..37b34cf
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+interface ISupplicantStaIfaceCallback {
+  oneway void onAnqpQueryDone(in byte[] bssid, in android.hardware.wifi.supplicant.AnqpData data, in android.hardware.wifi.supplicant.Hs20AnqpData hs20Data);
+  oneway void onAssociationRejected(in android.hardware.wifi.supplicant.AssociationRejectionData assocRejectData);
+  oneway void onAuthenticationTimeout(in byte[] bssid);
+  oneway void onBssTmHandlingDone(in android.hardware.wifi.supplicant.BssTmData tmData);
+  oneway void onBssidChanged(in android.hardware.wifi.supplicant.BssidChangeReason reason, in byte[] bssid);
+  oneway void onDisconnected(in byte[] bssid, in boolean locallyGenerated, in android.hardware.wifi.supplicant.StaIfaceReasonCode reasonCode);
+  oneway void onDppFailure(in android.hardware.wifi.supplicant.DppFailureCode code, in String ssid, in String channelList, in char[] bandList);
+  oneway void onDppProgress(in android.hardware.wifi.supplicant.DppProgressCode code);
+  oneway void onDppSuccess(in android.hardware.wifi.supplicant.DppEventType event);
+  oneway void onDppSuccessConfigReceived(in byte[] ssid, in String password, in byte[] psk, in android.hardware.wifi.supplicant.DppAkm securityAkm);
+  oneway void onDppSuccessConfigSent();
+  oneway void onEapFailure(in int errorCode);
+  oneway void onExtRadioWorkStart(in int id);
+  oneway void onExtRadioWorkTimeout(in int id);
+  oneway void onHs20DeauthImminentNotice(in byte[] bssid, in int reasonCode, in int reAuthDelayInSec, in String url);
+  oneway void onHs20IconQueryDone(in byte[] bssid, in String fileName, in byte[] data);
+  oneway void onHs20SubscriptionRemediation(in byte[] bssid, in android.hardware.wifi.supplicant.OsuMethod osuMethod, in String url);
+  oneway void onHs20TermsAndConditionsAcceptanceRequestedNotification(in byte[] bssid, in String url);
+  oneway void onNetworkAdded(in int id);
+  oneway void onNetworkNotFound(in byte[] ssid);
+  oneway void onNetworkRemoved(in int id);
+  oneway void onPmkCacheAdded(in long expirationTimeInSec, in byte[] serializedEntry);
+  oneway void onStateChanged(in android.hardware.wifi.supplicant.StaIfaceCallbackState newState, in byte[] bssid, in int id, in byte[] ssid, in boolean filsHlpSent);
+  oneway void onWpsEventFail(in byte[] bssid, in android.hardware.wifi.supplicant.WpsConfigError configError, in android.hardware.wifi.supplicant.WpsErrorIndication errorInd);
+  oneway void onWpsEventPbcOverlap();
+  oneway void onWpsEventSuccess();
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaNetwork.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaNetwork.aidl
new file mode 100644
index 0000000..18baea6
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaNetwork.aidl
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+interface ISupplicantStaNetwork {
+  void disable();
+  void enable(in boolean noConnect);
+  void enableSaePkOnlyMode(in boolean enable);
+  void enableSuiteBEapOpenSslCiphers();
+  void enableTlsSuiteBEapPhase1Param(in boolean enable);
+  android.hardware.wifi.supplicant.AuthAlgMask getAuthAlg();
+  byte[] getBssid();
+  String getEapAltSubjectMatch();
+  byte[] getEapAnonymousIdentity();
+  String getEapCACert();
+  String getEapCAPath();
+  String getEapClientCert();
+  String getEapDomainSuffixMatch();
+  boolean getEapEngine();
+  String getEapEngineId();
+  byte[] getEapIdentity();
+  android.hardware.wifi.supplicant.EapMethod getEapMethod();
+  byte[] getEapPassword();
+  android.hardware.wifi.supplicant.EapPhase2Method getEapPhase2Method();
+  String getEapPrivateKeyId();
+  String getEapSubjectMatch();
+  boolean getEdmg();
+  android.hardware.wifi.supplicant.GroupCipherMask getGroupCipher();
+  android.hardware.wifi.supplicant.GroupMgmtCipherMask getGroupMgmtCipher();
+  int getId();
+  String getIdStr();
+  String getInterfaceName();
+  android.hardware.wifi.supplicant.KeyMgmtMask getKeyMgmt();
+  android.hardware.wifi.supplicant.OcspType getOcsp();
+  android.hardware.wifi.supplicant.PairwiseCipherMask getPairwiseCipher();
+  android.hardware.wifi.supplicant.ProtoMask getProto();
+  byte[] getPsk();
+  String getPskPassphrase();
+  boolean getRequirePmf();
+  String getSaePassword();
+  String getSaePasswordId();
+  boolean getScanSsid();
+  byte[] getSsid();
+  android.hardware.wifi.supplicant.IfaceType getType();
+  String getWapiCertSuite();
+  byte[] getWepKey(in int keyIdx);
+  int getWepTxKeyIdx();
+  byte[] getWpsNfcConfigurationToken();
+  void registerCallback(in android.hardware.wifi.supplicant.ISupplicantStaNetworkCallback callback);
+  void select();
+  void sendNetworkEapIdentityResponse(in byte[] identity, in byte[] encryptedIdentity);
+  void sendNetworkEapSimGsmAuthFailure();
+  void sendNetworkEapSimGsmAuthResponse(in android.hardware.wifi.supplicant.NetworkResponseEapSimGsmAuthParams[] params);
+  void sendNetworkEapSimUmtsAuthFailure();
+  void sendNetworkEapSimUmtsAuthResponse(in android.hardware.wifi.supplicant.NetworkResponseEapSimUmtsAuthParams params);
+  void sendNetworkEapSimUmtsAutsResponse(in byte[] auts);
+  void setAuthAlg(in android.hardware.wifi.supplicant.AuthAlgMask authAlgMask);
+  void setBssid(in byte[] bssid);
+  void setEapAltSubjectMatch(in String match);
+  void setEapAnonymousIdentity(in byte[] identity);
+  void setEapCACert(in String path);
+  void setEapCAPath(in String path);
+  void setEapClientCert(in String path);
+  void setEapDomainSuffixMatch(in String match);
+  void setEapEncryptedImsiIdentity(in byte[] identity);
+  void setEapEngine(in boolean enable);
+  void setEapEngineID(in String id);
+  void setEapErp(in boolean enable);
+  void setEapIdentity(in byte[] identity);
+  void setEapMethod(in android.hardware.wifi.supplicant.EapMethod method);
+  void setEapPassword(in byte[] password);
+  void setEapPhase2Method(in android.hardware.wifi.supplicant.EapPhase2Method method);
+  void setEapPrivateKeyId(in String id);
+  void setEapSubjectMatch(in String match);
+  void setEdmg(in boolean enable);
+  void setGroupCipher(in android.hardware.wifi.supplicant.GroupCipherMask groupCipherMask);
+  void setGroupMgmtCipher(in android.hardware.wifi.supplicant.GroupMgmtCipherMask groupMgmtCipherMask);
+  void setIdStr(in String idStr);
+  void setKeyMgmt(in android.hardware.wifi.supplicant.KeyMgmtMask keyMgmtMask);
+  void setOcsp(in android.hardware.wifi.supplicant.OcspType ocspType);
+  void setPairwiseCipher(in android.hardware.wifi.supplicant.PairwiseCipherMask pairwiseCipherMask);
+  void setPmkCache(in byte[] serializedEntry);
+  void setProactiveKeyCaching(in boolean enable);
+  void setProto(in android.hardware.wifi.supplicant.ProtoMask protoMask);
+  void setPsk(in byte[] psk);
+  void setPskPassphrase(in String psk);
+  void setRequirePmf(in boolean enable);
+  void setSaeH2eMode(in android.hardware.wifi.supplicant.SaeH2eMode mode);
+  void setSaePassword(in String saePassword);
+  void setSaePasswordId(in String saePasswordId);
+  void setScanSsid(in boolean enable);
+  void setSsid(in byte[] ssid);
+  void setUpdateIdentifier(in int id);
+  void setWapiCertSuite(in String suite);
+  void setWepKey(in int keyIdx, in byte[] wepKey);
+  void setWepTxKeyIdx(in int keyIdx);
+  const int SSID_MAX_LEN_IN_BYTES = 32;
+  const int PSK_PASSPHRASE_MIN_LEN_IN_BYTES = 8;
+  const int PSK_PASSPHRASE_MAX_LEN_IN_BYTES = 63;
+  const int WEP_KEYS_MAX_NUM = 4;
+  const int WEP40_KEY_LEN_IN_BYTES = 5;
+  const int WEP104_KEY_LEN_IN_BYTES = 13;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaNetworkCallback.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaNetworkCallback.aidl
new file mode 100644
index 0000000..4f7584d
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaNetworkCallback.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+interface ISupplicantStaNetworkCallback {
+  oneway void onNetworkEapIdentityRequest();
+  oneway void onNetworkEapSimGsmAuthRequest(in android.hardware.wifi.supplicant.NetworkRequestEapSimGsmAuthParams params);
+  oneway void onNetworkEapSimUmtsAuthRequest(in android.hardware.wifi.supplicant.NetworkRequestEapSimUmtsAuthParams params);
+  oneway void onTransitionDisable(in android.hardware.wifi.supplicant.TransitionDisableIndication ind);
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/IfaceInfo.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/IfaceInfo.aidl
new file mode 100644
index 0000000..6706c8c
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/IfaceInfo.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+parcelable IfaceInfo {
+  android.hardware.wifi.supplicant.IfaceType type;
+  String name;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/IfaceType.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/IfaceType.aidl
new file mode 100644
index 0000000..557dbd7
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/IfaceType.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum IfaceType {
+  STA = 0,
+  P2P = 1,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/KeyMgmtMask.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/KeyMgmtMask.aidl
new file mode 100644
index 0000000..7228480
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/KeyMgmtMask.aidl
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum KeyMgmtMask {
+  WPA_EAP = 1,
+  WPA_PSK = 2,
+  NONE = 4,
+  IEEE8021X = 8,
+  FT_EAP = 32,
+  FT_PSK = 64,
+  OSEN = 32768,
+  WPA_EAP_SHA256 = 128,
+  WPA_PSK_SHA256 = 256,
+  SAE = 1024,
+  SUITE_B_192 = 131072,
+  OWE = 4194304,
+  DPP = 8388608,
+  WAPI_PSK = 4096,
+  WAPI_CERT = 8192,
+  FILS_SHA256 = 262144,
+  FILS_SHA384 = 524288,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/LegacyMode.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/LegacyMode.aidl
new file mode 100644
index 0000000..6896d75
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/LegacyMode.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum LegacyMode {
+  UNKNOWN = 0,
+  A_MODE = 1,
+  B_MODE = 2,
+  G_MODE = 3,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MacAddress.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MacAddress.aidl
new file mode 100644
index 0000000..d17930a
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MacAddress.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+parcelable MacAddress {
+  byte[] data;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MboAssocDisallowedReasonCode.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MboAssocDisallowedReasonCode.aidl
new file mode 100644
index 0000000..661165d
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MboAssocDisallowedReasonCode.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="byte") @VintfStability
+enum MboAssocDisallowedReasonCode {
+  RESERVED = 0,
+  UNSPECIFIED = 1,
+  MAX_NUM_STA_ASSOCIATED = 2,
+  AIR_INTERFACE_OVERLOADED = 3,
+  AUTH_SERVER_OVERLOADED = 4,
+  INSUFFICIENT_RSSI = 5,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MboCellularDataConnectionPrefValue.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MboCellularDataConnectionPrefValue.aidl
new file mode 100644
index 0000000..c4024d0
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MboCellularDataConnectionPrefValue.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum MboCellularDataConnectionPrefValue {
+  EXCLUDED = 0,
+  NOT_PREFERRED = 1,
+  PREFERRED = 255,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MboTransitionReasonCode.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MboTransitionReasonCode.aidl
new file mode 100644
index 0000000..caed095
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MboTransitionReasonCode.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="byte") @VintfStability
+enum MboTransitionReasonCode {
+  UNSPECIFIED = 0,
+  EXCESSIVE_FRAME_LOSS = 1,
+  EXCESSIVE_TRAFFIC_DELAY = 2,
+  INSUFFICIENT_BANDWIDTH = 3,
+  LOAD_BALANCING = 4,
+  LOW_RSSI = 5,
+  RX_EXCESSIVE_RETRIES = 6,
+  HIGH_INTERFERENCE = 7,
+  GRAY_ZONE = 8,
+  TRANSITION_TO_PREMIUM_AP = 9,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MiracastMode.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MiracastMode.aidl
new file mode 100644
index 0000000..6bc9e4d
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/MiracastMode.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="byte") @VintfStability
+enum MiracastMode {
+  DISABLED = 0,
+  SOURCE = 1,
+  SINK = 2,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/NetworkRequestEapSimGsmAuthParams.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/NetworkRequestEapSimGsmAuthParams.aidl
new file mode 100644
index 0000000..1f03bb8
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/NetworkRequestEapSimGsmAuthParams.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+parcelable NetworkRequestEapSimGsmAuthParams {
+  android.hardware.wifi.supplicant.GsmRand[] rands;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/NetworkRequestEapSimUmtsAuthParams.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/NetworkRequestEapSimUmtsAuthParams.aidl
new file mode 100644
index 0000000..956a799
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/NetworkRequestEapSimUmtsAuthParams.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+parcelable NetworkRequestEapSimUmtsAuthParams {
+  byte[] rand;
+  byte[] autn;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/NetworkResponseEapSimGsmAuthParams.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/NetworkResponseEapSimGsmAuthParams.aidl
new file mode 100644
index 0000000..29415b7
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/NetworkResponseEapSimGsmAuthParams.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+parcelable NetworkResponseEapSimGsmAuthParams {
+  byte[] kc;
+  byte[] sres;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/NetworkResponseEapSimUmtsAuthParams.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/NetworkResponseEapSimUmtsAuthParams.aidl
new file mode 100644
index 0000000..4e58dd8
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/NetworkResponseEapSimUmtsAuthParams.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+parcelable NetworkResponseEapSimUmtsAuthParams {
+  byte[] res;
+  byte[] ik;
+  byte[] ck;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/OceRssiBasedAssocRejectAttr.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/OceRssiBasedAssocRejectAttr.aidl
new file mode 100644
index 0000000..95a95bc
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/OceRssiBasedAssocRejectAttr.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@VintfStability
+parcelable OceRssiBasedAssocRejectAttr {
+  int deltaRssi;
+  int retryDelayS;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/OcspType.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/OcspType.aidl
new file mode 100644
index 0000000..89de811
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/OcspType.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum OcspType {
+  NONE = 0,
+  REQUEST_CERT_STATUS = 1,
+  REQUIRE_CERT_STATUS = 2,
+  REQUIRE_ALL_CERTS_STATUS = 3,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/OsuMethod.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/OsuMethod.aidl
new file mode 100644
index 0000000..1b99e2f
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/OsuMethod.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="byte") @VintfStability
+enum OsuMethod {
+  OMA_DM = 0,
+  SOAP_XML_SPP = 1,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pGroupCapabilityMask.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pGroupCapabilityMask.aidl
new file mode 100644
index 0000000..ffee12c
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pGroupCapabilityMask.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum P2pGroupCapabilityMask {
+  GROUP_OWNER = 1,
+  PERSISTENT_GROUP = 2,
+  GROUP_LIMIT = 4,
+  INTRA_BSS_DIST = 8,
+  CROSS_CONN = 16,
+  PERSISTENT_RECONN = 32,
+  GROUP_FORMATION = 64,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pProvDiscStatusCode.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pProvDiscStatusCode.aidl
new file mode 100644
index 0000000..c8e53b9
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pProvDiscStatusCode.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="byte") @VintfStability
+enum P2pProvDiscStatusCode {
+  SUCCESS = 0,
+  TIMEOUT = 1,
+  REJECTED = 2,
+  TIMEOUT_JOIN = 3,
+  INFO_UNAVAILABLE = 4,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pStatusCode.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pStatusCode.aidl
new file mode 100644
index 0000000..c7ad383
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pStatusCode.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum P2pStatusCode {
+  SUCCESS = 0,
+  FAIL_INFO_CURRENTLY_UNAVAILABLE = 1,
+  FAIL_INCOMPATIBLE_PARAMS = 2,
+  FAIL_LIMIT_REACHED = 3,
+  FAIL_INVALID_PARAMS = 4,
+  FAIL_UNABLE_TO_ACCOMMODATE = 5,
+  FAIL_PREV_PROTOCOL_ERROR = 6,
+  FAIL_NO_COMMON_CHANNELS = 7,
+  FAIL_UNKNOWN_GROUP = 8,
+  FAIL_BOTH_GO_INTENT_15 = 9,
+  FAIL_INCOMPATIBLE_PROV_METHOD = 10,
+  FAIL_REJECTED_BY_USER = 11,
+  SUCCESS_DEFERRED = 12,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/PairwiseCipherMask.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/PairwiseCipherMask.aidl
new file mode 100644
index 0000000..d9b00e1
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/PairwiseCipherMask.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum PairwiseCipherMask {
+  NONE = 1,
+  TKIP = 8,
+  CCMP = 16,
+  GCMP_128 = 64,
+  SMS4 = 128,
+  GCMP_256 = 256,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ProtoMask.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ProtoMask.aidl
new file mode 100644
index 0000000..de92428
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ProtoMask.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum ProtoMask {
+  WPA = 1,
+  RSN = 2,
+  WAPI = 4,
+  OSEN = 8,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/RxFilterType.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/RxFilterType.aidl
new file mode 100644
index 0000000..63f5bf2
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/RxFilterType.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="byte") @VintfStability
+enum RxFilterType {
+  V4_MULTICAST = 0,
+  V6_MULTICAST = 1,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/SaeH2eMode.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/SaeH2eMode.aidl
new file mode 100644
index 0000000..978c337
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/SaeH2eMode.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="byte") @VintfStability
+enum SaeH2eMode {
+  DISABLED = 0,
+  H2E_OPTIONAL = 1,
+  H2E_MANDATORY = 2,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/StaIfaceCallbackState.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/StaIfaceCallbackState.aidl
new file mode 100644
index 0000000..d78cfa2
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/StaIfaceCallbackState.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum StaIfaceCallbackState {
+  DISCONNECTED = 0,
+  IFACE_DISABLED = 1,
+  INACTIVE = 2,
+  SCANNING = 3,
+  AUTHENTICATING = 4,
+  ASSOCIATING = 5,
+  ASSOCIATED = 6,
+  FOURWAY_HANDSHAKE = 7,
+  GROUP_HANDSHAKE = 8,
+  COMPLETED = 9,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/StaIfaceReasonCode.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/StaIfaceReasonCode.aidl
new file mode 100644
index 0000000..f26e7c5
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/StaIfaceReasonCode.aidl
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum StaIfaceReasonCode {
+  UNSPECIFIED = 1,
+  PREV_AUTH_NOT_VALID = 2,
+  DEAUTH_LEAVING = 3,
+  DISASSOC_DUE_TO_INACTIVITY = 4,
+  DISASSOC_AP_BUSY = 5,
+  CLASS2_FRAME_FROM_NONAUTH_STA = 6,
+  CLASS3_FRAME_FROM_NONASSOC_STA = 7,
+  DISASSOC_STA_HAS_LEFT = 8,
+  STA_REQ_ASSOC_WITHOUT_AUTH = 9,
+  PWR_CAPABILITY_NOT_VALID = 10,
+  SUPPORTED_CHANNEL_NOT_VALID = 11,
+  BSS_TRANSITION_DISASSOC = 12,
+  INVALID_IE = 13,
+  MICHAEL_MIC_FAILURE = 14,
+  FOURWAY_HANDSHAKE_TIMEOUT = 15,
+  GROUP_KEY_UPDATE_TIMEOUT = 16,
+  IE_IN_4WAY_DIFFERS = 17,
+  GROUP_CIPHER_NOT_VALID = 18,
+  PAIRWISE_CIPHER_NOT_VALID = 19,
+  AKMP_NOT_VALID = 20,
+  UNSUPPORTED_RSN_IE_VERSION = 21,
+  INVALID_RSN_IE_CAPAB = 22,
+  IEEE_802_1X_AUTH_FAILED = 23,
+  CIPHER_SUITE_REJECTED = 24,
+  TDLS_TEARDOWN_UNREACHABLE = 25,
+  TDLS_TEARDOWN_UNSPECIFIED = 26,
+  SSP_REQUESTED_DISASSOC = 27,
+  NO_SSP_ROAMING_AGREEMENT = 28,
+  BAD_CIPHER_OR_AKM = 29,
+  NOT_AUTHORIZED_THIS_LOCATION = 30,
+  SERVICE_CHANGE_PRECLUDES_TS = 31,
+  UNSPECIFIED_QOS_REASON = 32,
+  NOT_ENOUGH_BANDWIDTH = 33,
+  DISASSOC_LOW_ACK = 34,
+  EXCEEDED_TXOP = 35,
+  STA_LEAVING = 36,
+  END_TS_BA_DLS = 37,
+  UNKNOWN_TS_BA = 38,
+  TIMEOUT = 39,
+  PEERKEY_MISMATCH = 45,
+  AUTHORIZED_ACCESS_LIMIT_REACHED = 46,
+  EXTERNAL_SERVICE_REQUIREMENTS = 47,
+  INVALID_FT_ACTION_FRAME_COUNT = 48,
+  INVALID_PMKID = 49,
+  INVALID_MDE = 50,
+  INVALID_FTE = 51,
+  MESH_PEERING_CANCELLED = 52,
+  MESH_MAX_PEERS = 53,
+  MESH_CONFIG_POLICY_VIOLATION = 54,
+  MESH_CLOSE_RCVD = 55,
+  MESH_MAX_RETRIES = 56,
+  MESH_CONFIRM_TIMEOUT = 57,
+  MESH_INVALID_GTK = 58,
+  MESH_INCONSISTENT_PARAMS = 59,
+  MESH_INVALID_SECURITY_CAP = 60,
+  MESH_PATH_ERROR_NO_PROXY_INFO = 61,
+  MESH_PATH_ERROR_NO_FORWARDING_INFO = 62,
+  MESH_PATH_ERROR_DEST_UNREACHABLE = 63,
+  MAC_ADDRESS_ALREADY_EXISTS_IN_MBSS = 64,
+  MESH_CHANNEL_SWITCH_REGULATORY_REQ = 65,
+  MESH_CHANNEL_SWITCH_UNSPECIFIED = 66,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/StaIfaceStatusCode.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/StaIfaceStatusCode.aidl
new file mode 100644
index 0000000..13529a5
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/StaIfaceStatusCode.aidl
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum StaIfaceStatusCode {
+  SUCCESS = 0,
+  UNSPECIFIED_FAILURE = 1,
+  TDLS_WAKEUP_ALTERNATE = 2,
+  TDLS_WAKEUP_REJECT = 3,
+  SECURITY_DISABLED = 5,
+  UNACCEPTABLE_LIFETIME = 6,
+  NOT_IN_SAME_BSS = 7,
+  CAPS_UNSUPPORTED = 10,
+  REASSOC_NO_ASSOC = 11,
+  ASSOC_DENIED_UNSPEC = 12,
+  NOT_SUPPORTED_AUTH_ALG = 13,
+  UNKNOWN_AUTH_TRANSACTION = 14,
+  CHALLENGE_FAIL = 15,
+  AUTH_TIMEOUT = 16,
+  AP_UNABLE_TO_HANDLE_NEW_STA = 17,
+  ASSOC_DENIED_RATES = 18,
+  ASSOC_DENIED_NOSHORT = 19,
+  SPEC_MGMT_REQUIRED = 22,
+  PWR_CAPABILITY_NOT_VALID = 23,
+  SUPPORTED_CHANNEL_NOT_VALID = 24,
+  ASSOC_DENIED_NO_SHORT_SLOT_TIME = 25,
+  ASSOC_DENIED_NO_HT = 27,
+  R0KH_UNREACHABLE = 28,
+  ASSOC_DENIED_NO_PCO = 29,
+  ASSOC_REJECTED_TEMPORARILY = 30,
+  ROBUST_MGMT_FRAME_POLICY_VIOLATION = 31,
+  UNSPECIFIED_QOS_FAILURE = 32,
+  DENIED_INSUFFICIENT_BANDWIDTH = 33,
+  DENIED_POOR_CHANNEL_CONDITIONS = 34,
+  DENIED_QOS_NOT_SUPPORTED = 35,
+  REQUEST_DECLINED = 37,
+  INVALID_PARAMETERS = 38,
+  REJECTED_WITH_SUGGESTED_CHANGES = 39,
+  INVALID_IE = 40,
+  GROUP_CIPHER_NOT_VALID = 41,
+  PAIRWISE_CIPHER_NOT_VALID = 42,
+  AKMP_NOT_VALID = 43,
+  UNSUPPORTED_RSN_IE_VERSION = 44,
+  INVALID_RSN_IE_CAPAB = 45,
+  CIPHER_REJECTED_PER_POLICY = 46,
+  TS_NOT_CREATED = 47,
+  DIRECT_LINK_NOT_ALLOWED = 48,
+  DEST_STA_NOT_PRESENT = 49,
+  DEST_STA_NOT_QOS_STA = 50,
+  ASSOC_DENIED_LISTEN_INT_TOO_LARGE = 51,
+  INVALID_FT_ACTION_FRAME_COUNT = 52,
+  INVALID_PMKID = 53,
+  INVALID_MDIE = 54,
+  INVALID_FTIE = 55,
+  REQUESTED_TCLAS_NOT_SUPPORTED = 56,
+  INSUFFICIENT_TCLAS_PROCESSING_RESOURCES = 57,
+  TRY_ANOTHER_BSS = 58,
+  GAS_ADV_PROTO_NOT_SUPPORTED = 59,
+  NO_OUTSTANDING_GAS_REQ = 60,
+  GAS_RESP_NOT_RECEIVED = 61,
+  STA_TIMED_OUT_WAITING_FOR_GAS_RESP = 62,
+  GAS_RESP_LARGER_THAN_LIMIT = 63,
+  REQ_REFUSED_HOME = 64,
+  ADV_SRV_UNREACHABLE = 65,
+  REQ_REFUSED_SSPN = 67,
+  REQ_REFUSED_UNAUTH_ACCESS = 68,
+  INVALID_RSNIE = 72,
+  U_APSD_COEX_NOT_SUPPORTED = 73,
+  U_APSD_COEX_MODE_NOT_SUPPORTED = 74,
+  BAD_INTERVAL_WITH_U_APSD_COEX = 75,
+  ANTI_CLOGGING_TOKEN_REQ = 76,
+  FINITE_CYCLIC_GROUP_NOT_SUPPORTED = 77,
+  CANNOT_FIND_ALT_TBTT = 78,
+  TRANSMISSION_FAILURE = 79,
+  REQ_TCLAS_NOT_SUPPORTED = 80,
+  TCLAS_RESOURCES_EXCHAUSTED = 81,
+  REJECTED_WITH_SUGGESTED_BSS_TRANSITION = 82,
+  REJECT_WITH_SCHEDULE = 83,
+  REJECT_NO_WAKEUP_SPECIFIED = 84,
+  SUCCESS_POWER_SAVE_MODE = 85,
+  PENDING_ADMITTING_FST_SESSION = 86,
+  PERFORMING_FST_NOW = 87,
+  PENDING_GAP_IN_BA_WINDOW = 88,
+  REJECT_U_PID_SETTING = 89,
+  REFUSED_EXTERNAL_REASON = 92,
+  REFUSED_AP_OUT_OF_MEMORY = 93,
+  REJECTED_EMERGENCY_SERVICE_NOT_SUPPORTED = 94,
+  QUERY_RESP_OUTSTANDING = 95,
+  REJECT_DSE_BAND = 96,
+  TCLAS_PROCESSING_TERMINATED = 97,
+  TS_SCHEDULE_CONFLICT = 98,
+  DENIED_WITH_SUGGESTED_BAND_AND_CHANNEL = 99,
+  MCCAOP_RESERVATION_CONFLICT = 100,
+  MAF_LIMIT_EXCEEDED = 101,
+  MCCA_TRACK_LIMIT_EXCEEDED = 102,
+  DENIED_DUE_TO_SPECTRUM_MANAGEMENT = 103,
+  ASSOC_DENIED_NO_VHT = 104,
+  ENABLEMENT_DENIED = 105,
+  RESTRICTION_FROM_AUTHORIZED_GDB = 106,
+  AUTHORIZATION_DEENABLED = 107,
+  FILS_AUTHENTICATION_FAILURE = 112,
+  UNKNOWN_AUTHENTICATION_SERVER = 113,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/SupplicantStatusCode.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/SupplicantStatusCode.aidl
new file mode 100644
index 0000000..32d71a3
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/SupplicantStatusCode.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum SupplicantStatusCode {
+  SUCCESS = 0,
+  FAILURE_UNKNOWN = 1,
+  FAILURE_ARGS_INVALID = 2,
+  FAILURE_IFACE_INVALID = 3,
+  FAILURE_IFACE_UNKNOWN = 4,
+  FAILURE_IFACE_EXISTS = 5,
+  FAILURE_IFACE_DISABLED = 6,
+  FAILURE_IFACE_NOT_DISCONNECTED = 7,
+  FAILURE_NETWORK_INVALID = 8,
+  FAILURE_NETWORK_UNKNOWN = 9,
+  FAILURE_UNSUPPORTED = 10,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/TransitionDisableIndication.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/TransitionDisableIndication.aidl
new file mode 100644
index 0000000..7c63217
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/TransitionDisableIndication.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum TransitionDisableIndication {
+  USE_WPA3_PERSONAL = 1,
+  USE_SAE_PK = 2,
+  USE_WPA3_ENTERPRISE = 4,
+  USE_ENHANCED_OPEN = 8,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WifiTechnology.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WifiTechnology.aidl
new file mode 100644
index 0000000..ad36e68
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WifiTechnology.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum WifiTechnology {
+  UNKNOWN = 0,
+  LEGACY = 1,
+  HT = 2,
+  VHT = 3,
+  HE = 4,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpaDriverCapabilitiesMask.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpaDriverCapabilitiesMask.aidl
new file mode 100644
index 0000000..43772af
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpaDriverCapabilitiesMask.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum WpaDriverCapabilitiesMask {
+  MBO = 1,
+  OCE = 2,
+  SAE_PK = 4,
+  WFD_R2 = 8,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpsConfigError.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpsConfigError.aidl
new file mode 100644
index 0000000..c48b282
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpsConfigError.aidl
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum WpsConfigError {
+  NO_ERROR = 0,
+  OOB_IFACE_READ_ERROR = 1,
+  DECRYPTION_CRC_FAILURE = 2,
+  CHAN_24_NOT_SUPPORTED = 3,
+  CHAN_50_NOT_SUPPORTED = 4,
+  SIGNAL_TOO_WEAK = 5,
+  NETWORK_AUTH_FAILURE = 6,
+  NETWORK_ASSOC_FAILURE = 7,
+  NO_DHCP_RESPONSE = 8,
+  FAILED_DHCP_CONFIG = 9,
+  IP_ADDR_CONFLICT = 10,
+  NO_CONN_TO_REGISTRAR = 11,
+  MULTIPLE_PBC_DETECTED = 12,
+  ROGUE_SUSPECTED = 13,
+  DEVICE_BUSY = 14,
+  SETUP_LOCKED = 15,
+  MSG_TIMEOUT = 16,
+  REG_SESS_TIMEOUT = 17,
+  DEV_PASSWORD_AUTH_FAILURE = 18,
+  CHAN_60G_NOT_SUPPORTED = 19,
+  PUBLIC_KEY_HASH_MISMATCH = 20,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpsConfigMethods.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpsConfigMethods.aidl
new file mode 100644
index 0000000..c98c479
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpsConfigMethods.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum WpsConfigMethods {
+  USBA = 1,
+  ETHERNET = 2,
+  LABEL = 4,
+  DISPLAY = 8,
+  EXT_NFC_TOKEN = 16,
+  INT_NFC_TOKEN = 32,
+  NFC_INTERFACE = 64,
+  PUSHBUTTON = 128,
+  KEYPAD = 256,
+  VIRT_PUSHBUTTON = 640,
+  PHY_PUSHBUTTON = 1152,
+  P2PS = 4096,
+  VIRT_DISPLAY = 8200,
+  PHY_DISPLAY = 16392,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpsDevPasswordId.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpsDevPasswordId.aidl
new file mode 100644
index 0000000..975f1ab
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpsDevPasswordId.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum WpsDevPasswordId {
+  DEFAULT = 0,
+  USER_SPECIFIED = 1,
+  MACHINE_SPECIFIED = 2,
+  REKEY = 3,
+  PUSHBUTTON = 4,
+  REGISTRAR_SPECIFIED = 5,
+  NFC_CONNECTION_HANDOVER = 7,
+  P2PS_DEFAULT = 8,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpsErrorIndication.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpsErrorIndication.aidl
new file mode 100644
index 0000000..50e69ff
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpsErrorIndication.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum WpsErrorIndication {
+  NO_ERROR = 0,
+  SECURITY_TKIP_ONLY_PROHIBITED = 1,
+  SECURITY_WEP_PROHIBITED = 2,
+  AUTH_FAILURE = 3,
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpsProvisionMethod.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpsProvisionMethod.aidl
new file mode 100644
index 0000000..f6dba23
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/WpsProvisionMethod.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum WpsProvisionMethod {
+  PBC = 0,
+  DISPLAY = 1,
+  KEYPAD = 2,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/AnqpData.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/AnqpData.aidl
new file mode 100644
index 0000000..5bc1015
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/AnqpData.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * ANQP data for IEEE Std 802.11-2016.
+ * The format of the data within these elements follows the IEEE
+ * Std 802.11-2016 standard, section 9.4.5.
+ */
+@VintfStability
+parcelable AnqpData {
+    byte[] venueName;
+    byte[] roamingConsortium;
+    byte[] ipAddrTypeAvailability;
+    byte[] naiRealm;
+    byte[] anqp3gppCellularNetwork;
+    byte[] domainName;
+    byte[] venueUrl;
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/AnqpInfoId.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/AnqpInfoId.aidl
new file mode 100644
index 0000000..7b2eb23
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/AnqpInfoId.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * Access Network Query Protocol info ID elements
+ * for IEEE Std 802.11u-2011.
+ */
+@VintfStability
+@Backing(type="int")
+enum AnqpInfoId {
+    VENUE_NAME = 258,
+    ROAMING_CONSORTIUM = 261,
+    IP_ADDR_TYPE_AVAILABILITY = 262,
+    NAI_REALM = 263,
+    ANQP_3GPP_CELLULAR_NETWORK = 264,
+    DOMAIN_NAME = 268,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/AssociationRejectionData.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/AssociationRejectionData.aidl
new file mode 100644
index 0000000..5673021
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/AssociationRejectionData.aidl
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+import android.hardware.wifi.supplicant.MboAssocDisallowedReasonCode;
+import android.hardware.wifi.supplicant.OceRssiBasedAssocRejectAttr;
+import android.hardware.wifi.supplicant.StaIfaceStatusCode;
+
+/**
+ * Association Rejection related information.
+ */
+@VintfStability
+parcelable AssociationRejectionData {
+    /**
+     * SSID of the AP that rejected the association.
+     */
+    byte[] ssid;
+    /**
+     * BSSID of the AP that rejected the association.
+     */
+    byte[/* 6 */] bssid;
+    /*
+     * 802.11 code to indicate the reject reason.
+     * Refer to section 8.4.1.9 of IEEE 802.11 spec.
+     */
+    StaIfaceStatusCode statusCode;
+    /*
+     * Flag to indicate that failure is due to timeout rather than
+     * explicit rejection response from the AP.
+     */
+    boolean timedOut;
+    /**
+     * Flag to indicate that MboAssocDisallowedReasonCode is present
+     * in the (Re-)Association response frame.
+     */
+    boolean isMboAssocDisallowedReasonCodePresent;
+    /**
+     * mboAssocDisallowedReason is extracted from MBO association disallowed attribute
+     * in (Re-)Association response frame to indicate that the AP is not accepting new
+     * associations.
+     * Refer MBO spec v1.2 section 4.2.4 Table 13 for the details of reason code.
+     * The value is undefined if isMboAssocDisallowedReasonCodePresent is false.
+     */
+    MboAssocDisallowedReasonCode mboAssocDisallowedReason;
+    /**
+     * Flag to indicate that OceRssiBasedAssocRejectAttr is present
+     * in the (Re-)Association response frame.
+     */
+    boolean isOceRssiBasedAssocRejectAttrPresent;
+    /*
+     * OCE RSSI-based (Re-)Association rejection attribute.
+     * The contents are undefined if isOceRssiBasedAssocRejectAttrPresent is false.
+     */
+    OceRssiBasedAssocRejectAttr oceRssiBasedAssocRejectData;
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/AuthAlgMask.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/AuthAlgMask.aidl
new file mode 100644
index 0000000..039d41d
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/AuthAlgMask.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * Possible mask of values for AuthAlg param.
+ * See /external/wpa_supplicant_8/src/common/defs.h for
+ * the historical values (starting at WPA_AUTH_ALG_OPEN).
+ */
+@VintfStability
+@Backing(type="int")
+enum AuthAlgMask {
+    OPEN = 1 << 0,
+    SHARED = 1 << 1,
+    LEAP = 1 << 2,
+    SAE = 1 << 4,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/BssTmData.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/BssTmData.aidl
new file mode 100644
index 0000000..233e54a
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/BssTmData.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+import android.hardware.wifi.supplicant.BssTmDataFlagsMask;
+import android.hardware.wifi.supplicant.BssTmStatusCode;
+import android.hardware.wifi.supplicant.MboCellularDataConnectionPrefValue;
+import android.hardware.wifi.supplicant.MboTransitionReasonCode;
+
+/**
+ * Data retrieved from received BSS transition management request frame.
+ */
+@VintfStability
+parcelable BssTmData {
+    /*
+     * Status code filled in BSS transition management response frame
+     */
+    BssTmStatusCode status;
+    /*
+     * Bitmask of BssTmDataFlagsMask
+     */
+    BssTmDataFlagsMask flags;
+    /*
+     * Duration for which STA shouldn't try to re-associate.
+     */
+    int assocRetryDelayMs;
+    /*
+     * Reason for BSS transition request.
+     */
+    MboTransitionReasonCode mboTransitionReason;
+    /*
+     * Cellular Data Connection preference value.
+     */
+    MboCellularDataConnectionPrefValue mboCellPreference;
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/BssTmDataFlagsMask.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/BssTmDataFlagsMask.aidl
new file mode 100644
index 0000000..1eb75f4
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/BssTmDataFlagsMask.aidl
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * Bitmask of various information retrieved from BSS transition management request frame.
+ */
+@VintfStability
+@Backing(type="int")
+enum BssTmDataFlagsMask {
+    /**
+     * Preferred candidate list included.
+     */
+    WNM_MODE_PREFERRED_CANDIDATE_LIST_INCLUDED = 1 << 0,
+    /**
+     * Abridged.
+     */
+    WNM_MODE_ABRIDGED = 1 << 1,
+    /**
+     * Disassociation Imminent.
+     */
+    WNM_MODE_DISASSOCIATION_IMMINENT = 1 << 2,
+    /**
+     * BSS termination included.
+     */
+    WNM_MODE_BSS_TERMINATION_INCLUDED = 1 << 3,
+    /**
+     * ESS Disassociation Imminent.
+     */
+    WNM_MODE_ESS_DISASSOCIATION_IMMINENT = 1 << 4,
+    /**
+     * MBO transition reason code included.
+     */
+    MBO_TRANSITION_REASON_CODE_INCLUDED = 1 << 5,
+    /**
+     * MBO retry delay time included.
+     */
+    MBO_ASSOC_RETRY_DELAY_INCLUDED = 1 << 6,
+    /**
+     * MBO cellular data connection preference value included.
+     */
+    MBO_CELLULAR_DATA_CONNECTION_PREFERENCE_INCLUDED = 1 << 7,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/BssTmStatusCode.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/BssTmStatusCode.aidl
new file mode 100644
index 0000000..51fbfed
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/BssTmStatusCode.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * IEEE Std 802.11-2016 - Table 9-357.
+ * BTM status code filled in BSS transition management response frame.
+ */
+@VintfStability
+@Backing(type="byte")
+enum BssTmStatusCode {
+    ACCEPT = 0,
+    REJECT_UNSPECIFIED = 1,
+    REJECT_INSUFFICIENT_BEACON = 2,
+    REJECT_INSUFFICIENT_CAPABITY = 3,
+    REJECT_BSS_TERMINATION_UNDESIRED = 4,
+    REJECT_BSS_TERMINATION_DELAY_REQUEST = 5,
+    REJECT_STA_CANDIDATE_LIST_PROVIDED = 6,
+    REJECT_NO_SUITABLE_CANDIDATES = 7,
+    REJECT_LEAVING_ESS = 8,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/BssidChangeReason.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/BssidChangeReason.aidl
new file mode 100644
index 0000000..8532bd7
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/BssidChangeReason.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * BSSID change Reasons.
+ */
+@VintfStability
+@Backing(type="byte")
+enum BssidChangeReason {
+    /**
+     * Started association with new bssid.
+     */
+    ASSOC_START = 0,
+    /**
+     * Completed association with new bssid.
+     */
+    ASSOC_COMPLETE = 1,
+    /**
+     * Dis-association with current bssid.
+     */
+    DISASSOC = 2,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/BtCoexistenceMode.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/BtCoexistenceMode.aidl
new file mode 100644
index 0000000..4972744
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/BtCoexistenceMode.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * Enum describing the modes of BT coexistence supported
+ * via driver commands.
+ */
+@VintfStability
+@Backing(type="byte")
+enum BtCoexistenceMode {
+    ENABLED = 0,
+    DISABLED = 1,
+    SENSE = 2,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ConnectionCapabilities.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ConnectionCapabilities.aidl
new file mode 100644
index 0000000..1718413
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ConnectionCapabilities.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+import android.hardware.wifi.supplicant.LegacyMode;
+import android.hardware.wifi.supplicant.WifiTechnology;
+
+/**
+ * Connection Capabilities supported by current network and device
+ */
+@VintfStability
+parcelable ConnectionCapabilities {
+    /**
+     * Wifi Technology
+     */
+    WifiTechnology technology;
+    /**
+     * channel bandwidth
+     */
+    int channelBandwidth;
+    /**
+     * max number of Tx spatial streams
+     */
+    int maxNumberTxSpatialStreams;
+    /**
+     * max number of Rx spatial streams
+     */
+    int maxNumberRxSpatialStreams;
+    /**
+     * detailed network mode for legacy network
+     */
+    LegacyMode legacyMode;
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DebugLevel.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DebugLevel.aidl
new file mode 100644
index 0000000..7caa406
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DebugLevel.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * Debug levels for the supplicant.
+ * Only log messages with a level greater than the set level
+ * (via |setDebugParams|) will be logged.
+ */
+@VintfStability
+@Backing(type="int")
+enum DebugLevel {
+    EXCESSIVE = 0,
+    MSGDUMP = 1,
+    DEBUG = 2,
+    INFO = 3,
+    WARNING = 4,
+    ERROR = 5,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppAkm.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppAkm.aidl
new file mode 100644
index 0000000..63fff54
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppAkm.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * DppAkm: The various AKMs that can be provisioned using DPP.
+ */
+@VintfStability
+@Backing(type="int")
+enum DppAkm {
+    PSK,
+    PSK_SAE,
+    SAE,
+    DPP,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppCurve.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppCurve.aidl
new file mode 100644
index 0000000..ea57505
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppCurve.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * DppCurve: Elliptic curve cryptography type used to generate DPP
+ * public/private key pair.
+ */
+@VintfStability
+@Backing(type="int")
+enum DppCurve {
+    PRIME256V1,
+    SECP384R1,
+    SECP521R1,
+    BRAINPOOLP256R1,
+    BRAINPOOLP384R1,
+    BRAINPOOLP512R1,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppEventType.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppEventType.aidl
new file mode 100644
index 0000000..4b9b38b
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppEventType.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * DppEventType: Major events for DPP (Easy Connect) Configurator
+ */
+@VintfStability
+@Backing(type="int")
+enum DppEventType {
+    CONFIGURATION_SENT,
+    CONFIGURATION_APPLIED,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppFailureCode.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppFailureCode.aidl
new file mode 100644
index 0000000..5c0c6e8
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppFailureCode.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * DppFailureCode: Error codes for DPP (Easy Connect)
+ */
+@VintfStability
+@Backing(type="int")
+enum DppFailureCode {
+    INVALID_URI,
+    AUTHENTICATION,
+    NOT_COMPATIBLE,
+    CONFIGURATION,
+    BUSY,
+    TIMEOUT,
+    FAILURE,
+    NOT_SUPPORTED,
+    CONFIGURATION_REJECTED,
+    CANNOT_FIND_NETWORK,
+    ENROLLEE_AUTHENTICATION,
+    /**
+     * Failure to generate a DPP URI.
+     */
+    URI_GENERATION,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppNetRole.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppNetRole.aidl
new file mode 100644
index 0000000..d92cfa3
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppNetRole.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * DppNetRole: The network role that the configurator offers the enrollee.
+ */
+@VintfStability
+@Backing(type="int")
+enum DppNetRole {
+    STA,
+    AP,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppProgressCode.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppProgressCode.aidl
new file mode 100644
index 0000000..f8b35c0
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppProgressCode.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * DppProgressCode: Progress codes for DPP (Easy Connect)
+ */
+@VintfStability
+@Backing(type="int")
+enum DppProgressCode {
+    AUTHENTICATION_SUCCESS,
+    RESPONSE_PENDING,
+    CONFIGURATION_SENT_WAITING_RESPONSE,
+    CONFIGURATION_ACCEPTED,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppResponderBootstrapInfo.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppResponderBootstrapInfo.aidl
new file mode 100644
index 0000000..4f4778d
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/DppResponderBootstrapInfo.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * DPP bootstrap info generated for responder mode operation
+ */
+@VintfStability
+parcelable DppResponderBootstrapInfo {
+    /**
+     * Generated bootstrap identifier
+     */
+    int bootstrapId;
+    /**
+     * The Wi-Fi channel that the DPP responder is listening on.
+     */
+    int listenChannel;
+    /**
+     * Bootstrapping URI per DPP specification, "section 5.2 Bootstrapping
+     * information", may contain listen channel, MAC address, public key, or other information.
+     */
+    String uri;
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/EapErrorCode.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/EapErrorCode.aidl
new file mode 100644
index 0000000..49f9e34
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/EapErrorCode.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/*
+ * EapErrorCode: Error code for EAP or EAP Method as per RFC-4186
+ */
+@VintfStability
+@Backing(type="int")
+enum EapErrorCode {
+    SIM_GENERAL_FAILURE_AFTER_AUTH = 0,
+    SIM_TEMPORARILY_DENIED = 1026,
+    SIM_NOT_SUBSCRIBED = 1031,
+    SIM_GENERAL_FAILURE_BEFORE_AUTH = 16384,
+    SIM_VENDOR_SPECIFIC_EXPIRED_CERT = 16385,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/EapMethod.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/EapMethod.aidl
new file mode 100644
index 0000000..351fb6c
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/EapMethod.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * Possble values for EapMethod param.
+ */
+@VintfStability
+@Backing(type="int")
+enum EapMethod {
+    PEAP = 0,
+    TLS = 1,
+    TTLS = 2,
+    PWD = 3,
+    SIM = 4,
+    AKA = 5,
+    AKA_PRIME = 6,
+    WFA_UNAUTH_TLS = 7,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/EapPhase2Method.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/EapPhase2Method.aidl
new file mode 100644
index 0000000..a7eeca8
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/EapPhase2Method.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * Possble values for Phase2Method param.
+ */
+@VintfStability
+@Backing(type="int")
+enum EapPhase2Method {
+    NONE = 0,
+    PAP = 1,
+    MSPAP = 2,
+    MSPAPV2 = 3,
+    GTC = 4,
+    SIM = 5,
+    AKA = 6,
+    AKA_PRIME = 7,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ExtRadioWorkDefaults.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ExtRadioWorkDefaults.aidl
new file mode 100644
index 0000000..7325ba2
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ExtRadioWorkDefaults.aidl
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+@VintfStability
+@Backing(type="int")
+enum ExtRadioWorkDefaults {
+    TIMEOUT_IN_SECS = 10,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/FreqRange.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/FreqRange.aidl
new file mode 100644
index 0000000..a88c011
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/FreqRange.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * Use to specify a range of frequencies.
+ * For example: 2412-2432,2462,5000-6000, etc.
+ */
+@VintfStability
+parcelable FreqRange {
+    int min;
+    int max;
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/GroupCipherMask.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/GroupCipherMask.aidl
new file mode 100644
index 0000000..99e9da0
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/GroupCipherMask.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * Possible mask of values for GroupCipher param.
+ * See /external/wpa_supplicant_8/src/common/defs.h for
+ * the historical values (starting at WPA_CIPHER_WEP40).
+ */
+@VintfStability
+@Backing(type="int")
+enum GroupCipherMask {
+    WEP40 = 1 << 1,
+    WEP104 = 1 << 2,
+    TKIP = 1 << 3,
+    CCMP = 1 << 4,
+    GTK_NOT_USED = 1 << 14,
+    /**
+     * GCMP-256 Group Cipher
+     */
+    GCMP_256 = 1 << 8,
+    /**
+     * SMS4 Group Cipher
+     */
+    SMS4 = 1 << 7,
+    /**
+     * GCMP-128 Group Cipher
+     */
+    GCMP_128 = 1 << 6,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/GroupMgmtCipherMask.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/GroupMgmtCipherMask.aidl
new file mode 100644
index 0000000..07544f0
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/GroupMgmtCipherMask.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * Possble mask of values for GroupMgmtCipher param.
+ * See /external/wpa_supplicant_8/src/common/defs.h for
+ * all possible values (starting at WPA_CIPHER_BIP_GMAC_128).
+ */
+@VintfStability
+@Backing(type="int")
+enum GroupMgmtCipherMask {
+    /**
+     * BIP_GMAC-128 Group Management Cipher
+     */
+    BIP_GMAC_128 = 1 << 11,
+    /**
+     * BIP_GMAC-256 Group Management Cipher
+     */
+    BIP_GMAC_256 = 1 << 12,
+    /**
+     * BIP_CMAC-256 Group Management Cipher
+     */
+    BIP_CMAC_256 = 1 << 13,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/GsmRand.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/GsmRand.aidl
new file mode 100644
index 0000000..4e31323
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/GsmRand.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * Byte array with expected length 16. Used by NetworkRequestEapSimGsmAuthParams
+ * to pass an array of byte arrays, as 2D arrays are not supported in AIDL.
+ *
+ * TODO (b/210705533): Replace this type with a 2D byte array.
+ */
+@VintfStability
+parcelable GsmRand {
+    byte[/* 16 */] data;
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/Hs20AnqpData.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/Hs20AnqpData.aidl
new file mode 100644
index 0000000..bdb9ec6
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/Hs20AnqpData.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * ANQP data for Hotspot 2.0.
+ * The format of the data within these elements follows the Hotspot 2.0
+ * standard.
+ */
+@VintfStability
+parcelable Hs20AnqpData {
+    byte[] operatorFriendlyName;
+    byte[] wanMetrics;
+    byte[] connectionCapability;
+    byte[] osuProvidersList;
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/Hs20AnqpSubtypes.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/Hs20AnqpSubtypes.aidl
new file mode 100644
index 0000000..e08411d
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/Hs20AnqpSubtypes.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * Access Network Query Protocol subtype elements
+ * for Hotspot 2.0.
+ */
+@VintfStability
+@Backing(type="int")
+enum Hs20AnqpSubtypes {
+    OPERATOR_FRIENDLY_NAME = 3,
+    WAN_METRICS = 4,
+    CONNECTION_CAPABILITY = 5,
+    OSU_PROVIDERS_LIST = 8,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicant.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicant.aidl
new file mode 100644
index 0000000..c17289d
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicant.aidl
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+import android.hardware.wifi.supplicant.DebugLevel;
+import android.hardware.wifi.supplicant.ISupplicantCallback;
+import android.hardware.wifi.supplicant.ISupplicantP2pIface;
+import android.hardware.wifi.supplicant.ISupplicantStaIface;
+import android.hardware.wifi.supplicant.IfaceInfo;
+import android.hardware.wifi.supplicant.IfaceType;
+
+/**
+ * Interface exposed by the supplicant AIDL service registered
+ * with the service manager. This is the root level object for
+ * any of the supplicant interactions.
+ */
+@VintfStability
+interface ISupplicant {
+    /**
+     * Default timeout (in seconds) for external radio work.
+     */
+    const int EXT_RADIO_WORK_TIMEOUT_IN_SECS = 10;
+
+    /**
+     * Registers a wireless interface in supplicant.
+     *
+     * @param ifName Name of the interface (e.g wlan0).
+     * @return AIDL interface object representing the interface if
+     *         successful, null otherwise.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_EXISTS|
+     */
+    @PropagateAllowBlocking ISupplicantP2pIface addP2pInterface(in String ifName);
+    @PropagateAllowBlocking ISupplicantStaIface addStaInterface(in String ifName);
+
+    /**
+     * Get the debug level set.
+     *
+     * @return one of |DebugLevel| values.
+     */
+    DebugLevel getDebugLevel();
+
+    /**
+     * Gets an AIDL interface object for the interface corresponding
+     * to an iface name which the supplicant already controls.
+     *
+     * @param ifName Name of the interface retrieved
+     *        using |listInterfaces|.
+     * @return AIDL interface object representing the interface if
+     *         successful, null otherwise.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_UNKNOWN|
+     */
+    @PropagateAllowBlocking ISupplicantP2pIface getP2pInterface(in String ifName);
+    @PropagateAllowBlocking ISupplicantStaIface getStaInterface(in String ifName);
+
+    /**
+     * Get whether the keys are shown in the debug logs or not.
+     *
+     * @return true if set, false otherwise.
+     */
+    boolean isDebugShowKeysEnabled();
+
+    /**
+     * Get whether the timestamps are shown in the debug logs or not.
+     *
+     * @return true if set, false otherwise.
+     */
+    boolean isDebugShowTimestampEnabled();
+
+    /**
+     * Retrieve a list of all interfaces controlled by the supplicant.
+     *
+     * The corresponding |ISupplicantIface| object for any interface can be
+     * retrieved using the proper |getInterface| method.
+     *
+     * @return List of all interfaces controlled by the supplicant.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     */
+    IfaceInfo[] listInterfaces();
+
+    /**
+     * Register for callbacks from the supplicant service.
+     *
+     * These callbacks are invoked for global events that are not specific
+     * to any interface or network. Registration of multiple callback
+     * objects is supported. These objects must be deleted when the corresponding
+     * client process is dead.
+     *
+     * @param callback An instance of the |ISupplicantCallback| AIDL interface
+     *        object.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     */
+    void registerCallback(in ISupplicantCallback callback);
+
+    /**
+     * Deregisters a wireless interface from supplicant.
+     *
+     * @param ifaceInfo Combination of the interface type and name (e.g wlan0).
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_UNKNOWN|
+     */
+    void removeInterface(in IfaceInfo ifaceInfo);
+
+    /**
+     * Set concurrency priority.
+     *
+     * When both P2P and STA mode ifaces are active, this must be used
+     * to prioritize either STA or P2P connection to resolve conflicts
+     * arising during single channel concurrency.
+     *
+     * @param type The type of iface to prioritize.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     */
+    void setConcurrencyPriority(in IfaceType type);
+
+    /**
+     * Set debug parameters for the supplicant.
+     *
+     * @param level Debug logging level for the supplicant.
+     *        (one of |DebugLevel| values).
+     * @param timestamp Determines whether to show timestamps in logs or
+     *        not.
+     * @param showKeys Determines whether to show keys in debug logs or
+     *        not.
+     *        CAUTION: Do not set this param in production code!
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     */
+    void setDebugParams(in DebugLevel level, in boolean showTimestamp, in boolean showKeys);
+
+    /**
+     * Terminate the service.
+     * This must de-register the service and clear all state. If this HAL
+     * supports the lazy HAL protocol, then this may trigger daemon to exit and
+     * wait to be restarted.
+     */
+    oneway void terminate();
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantCallback.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantCallback.aidl
new file mode 100644
index 0000000..6f15900
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantCallback.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * Callback Interface exposed by the supplicant service (ISupplicant).
+ *
+ * Clients need to host an instance of this AIDL interface object and
+ * pass a reference of the object to the supplicant via the
+ * |ISupplicant.registerCallback| method.
+ */
+@VintfStability
+interface ISupplicantCallback {
+    /**
+     * Used to indicate that a new interface has been created.
+     *
+     * @param ifaceName Name of the network interface, e.g., wlan0
+     */
+    oneway void onInterfaceCreated(in String ifaceName);
+
+    /**
+     * Used to indicate that an interface has been removed.
+     *
+     * @param ifaceName Name of the network interface, e.g., wlan0
+     */
+    oneway void onInterfaceRemoved(in String ifaceName);
+
+    /**
+     * Used to indicate that the supplicant daemon is terminating.
+     */
+    oneway void onTerminating();
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pIface.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pIface.aidl
new file mode 100644
index 0000000..5394f49
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pIface.aidl
@@ -0,0 +1,770 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+import android.hardware.wifi.supplicant.FreqRange;
+import android.hardware.wifi.supplicant.ISupplicantP2pIfaceCallback;
+import android.hardware.wifi.supplicant.ISupplicantP2pNetwork;
+import android.hardware.wifi.supplicant.IfaceType;
+import android.hardware.wifi.supplicant.MiracastMode;
+import android.hardware.wifi.supplicant.P2pGroupCapabilityMask;
+import android.hardware.wifi.supplicant.WpsConfigMethods;
+import android.hardware.wifi.supplicant.WpsProvisionMethod;
+
+/**
+ * Interface exposed by the supplicant for each P2P mode network
+ * interface (e.g p2p0) it controls.
+ */
+@VintfStability
+interface ISupplicantP2pIface {
+    /**
+     * This command can be used to add a bonjour service.
+     *
+     * @param query Hex dump of the query data.
+     * @param return Hex dump of the response data.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void addBonjourService(in byte[] query, in byte[] response);
+
+    /**
+     * Set up a P2P group owner manually (i.e., without group owner
+     * negotiation with a specific peer). This is also known as autonomous
+     * group owner. Optional |persistentNetworkId| may be used to specify
+     * restart of a persistent group.
+     *
+     * @param persistent Used to request a persistent group to be formed.
+     * @param persistentNetworkId Used to specify the restart of a persistent
+     *        group. Set to UINT32_MAX for a non-persistent group.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void addGroup(in boolean persistent, in int persistentNetworkId);
+
+    /**
+     * Set up a P2P group owner or join a group as a group client
+     * with the specified configuration.
+     *
+     * If joinExistingGroup is false, this device sets up a P2P group owner manually (i.e.,
+     * without group owner negotiation with a specific peer) with the specified SSID,
+     * passphrase, persistent mode, and frequency/band.
+     *
+     * If joinExistingGroup is true, this device acts as a group client and joins the group
+     * whose network name and group owner's MAC address matches the specified SSID
+     * and peer address without WPS process. If peerAddress is 00:00:00:00:00:00, the first found
+     * group whose network name matches the specified SSID is joined.
+     *
+     * @param ssid The SSID of this group.
+     * @param pskPassphrase The passphrase of this group.
+     * @param persistent Used to request a persistent group to be formed,
+     *        only applied for the group owner.
+     * @param freq The required frequency or band for this group.
+     *        only applied for the group owner.
+     *        The following values are supported:
+     *        0: automatic channel selection,
+     *        2: for 2.4GHz channels
+     *        5: for 5GHz channels
+     *        specific frequency, i.e., 2412, 5500, etc.
+     *        If an invalid band or unsupported frequency are specified, it fails.
+     * @param peerAddress the group owner's MAC address, only applied for the group client.
+     *        If the MAC is "00:00:00:00:00:00", the device must try to find a peer
+     *        whose network name matches the specified SSID.
+     * @param joinExistingGroup if true, join a group as a group client; otherwise,
+     *        create a group as a group owner.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void addGroupWithConfig(in byte[] ssid, in String pskPassphrase, in boolean persistent,
+            in int freq, in byte[] peerAddress, in boolean joinExistingGroup);
+
+    /**
+     * Add a new network to the interface.
+     *
+     * @return AIDL interface object representing the new network if
+     *         successful, null otherwise.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    @PropagateAllowBlocking ISupplicantP2pNetwork addNetwork();
+
+    /**
+     * This command can be used to add a UPNP service.
+     *
+     * @param version Version to be used.
+     * @package serviceName Service name to be used.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void addUpnpService(in int version, in String serviceName);
+
+    /**
+     * Cancel an ongoing P2P group formation and joining-a-group related
+     * operation. This operation unauthorizes the specific peer device (if any
+     * had been authorized to start group formation), stops P2P find (if in
+     * progress), stops pending operations for join-a-group, and removes the
+     * P2P group interface (if one was used) that is in the WPS provisioning
+     * step. If the WPS provisioning step has been completed, the group is not
+     * terminated.
+     *
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_NOT_STARTED|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void cancelConnect();
+
+    /**
+     * Cancel a previous service discovery request.
+     *
+     * @param identifier Identifier for the request to cancel.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_NOT_STARTED|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void cancelServiceDiscovery(in long identifier);
+
+    /**
+     * Cancel any ongoing WPS operations.
+     *
+     * @param groupIfName Group interface name to use.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void cancelWps(in String groupIfName);
+
+    /**
+     * Configure Extended Listen Timing.
+     *
+     * If enabled, listen state must be entered every |intervalInMillis| for at
+     * least |periodInMillis|. Both values have acceptable range of 1-65535
+     * (with interval obviously having to be larger than or equal to duration).
+     * If the P2P module is not idle at the time the Extended Listen Timing
+     * timeout occurs, the Listen State operation must be skipped.
+     *
+     * @param periodInMillis Period in milliseconds.
+     * @param intervalInMillis Interval in milliseconds.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void configureExtListen(in int periodInMillis, in int intervalInMillis);
+
+    /**
+     * Start P2P group formation with a discovered P2P peer. This includes
+     * optional group owner negotiation, group interface setup, provisioning,
+     * and establishing data connection.
+     *
+     * @param peerAddress MAC address of the device to connect to.
+     * @param provisionMethod Provisioning method to use.
+     * @param preSelectedPin Pin to be used, if |provisionMethod| uses one of the
+     *        preselected |PIN*| methods.
+     * @param joinExistingGroup Indicates that this is a command to join an
+     *        existing group as a client. It skips the group owner negotiation
+     *        part. This must send a Provision Discovery Request message to the
+     *        target group owner before associating for WPS provisioning.
+     * @param persistent Used to request a persistent group to be formed.
+     * @param goIntent Used to override the default Intent for this group owner
+     *        negotiation (Values from 1-15). Refer to section 4.1.6 in
+     *        Wi-Fi Peer-to-Peer (P2P) Technical Specification Version 1.7.
+     * @return Pin generated, if |provisionMethod| uses one of the
+     *         generated |PIN*| methods.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    String connect(in byte[] peerAddress, in WpsProvisionMethod provisionMethod,
+            in String preSelectedPin, in boolean joinExistingGroup, in boolean persistent,
+            in int goIntent);
+
+    /**
+     * Creates a NFC handover request message.
+     *
+     * @return Bytes representing the handover request as specified in
+     *         section 3.1.1 of NFC Connection Handover 1.2 Technical
+     *         Specification.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    byte[] createNfcHandoverRequestMessage();
+
+    /**
+     * Creates a NFC handover select message.
+     *
+     * @return Bytes representing the handover select as specified in
+     *         section 3.1.2 of NFC Connection Handover 1.2 Technical
+     *         Specification.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    byte[] createNfcHandoverSelectMessage();
+
+    /**
+     * Enable/Disable Wifi Display.
+     *
+     * @param enable true to enable, false to disable.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void enableWfd(in boolean enable);
+
+    /**
+     * Initiate a P2P service discovery with an optional timeout.
+     *
+     * @param timeoutInSec Max time to be spent is performing discovery.
+     *        Set to 0 to indefinely continue discovery until an explicit
+     *        |stopFind| is sent.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     *         |SupplicantStatusCode.FAILURE_IFACE_DISABLED|
+     */
+    void find(in int timeoutInSec);
+
+    /**
+     * Flush P2P peer table and state.
+     *
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void flush();
+
+    /**
+     * This command can be used to flush all services from the
+     * device.
+     *
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void flushServices();
+
+    /**
+     * Gets the MAC address of the device.
+     *
+     * @return MAC address of the device.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    byte[] getDeviceAddress();
+
+    /**
+     * Get whether EDMG(802.11ay) is enabled for this network.
+     *
+     * @return true if set, false otherwise.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    boolean getEdmg();
+
+    /**
+     * Gets the capability of the group which the device is a
+     * member of.
+     *
+     * @param peerAddress MAC address of the peer.
+     * @return Combination of |P2pGroupCapabilityMask| values.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    P2pGroupCapabilityMask getGroupCapability(in byte[] peerAddress);
+
+    /**
+     * Retrieves the name of the network interface.
+     *
+     * @return Name of the network interface, e.g., wlan0
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    String getName();
+
+    /**
+     * Gets an AIDL interface object for the network corresponding to the
+     * network id.
+     *
+     * Use |ISupplicantP2pNetwork.getId()| on the corresponding network AIDL
+     * interface object to retrieve the ID.
+     *
+     * @param id Network ID allocated to the corresponding network.
+     * @return AIDL interface object representing the new network if
+     *         successful, null otherwise.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_UNKNOWN|
+     */
+    @PropagateAllowBlocking ISupplicantP2pNetwork getNetwork(in int id);
+
+    /**
+     * Gets the operational SSID of the device.
+     *
+     * @param peerAddress MAC address of the peer.
+     * @return SSID of the device
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    byte[] getSsid(in byte[] peerAddress);
+
+    /**
+     * Retrieves the type of the network interface.
+     *
+     * @return Type of the network interface, e.g., STA.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    IfaceType getType();
+
+    /**
+     * Invite a device to a persistent group.
+     * If the peer device is the group owner of the persistent group, the peer
+     * parameter is not needed. Otherwise it is used to specify which
+     * device to invite. |goDeviceAddress| parameter may be used to override
+     * the group owner device address for Invitation Request should it not be
+     * known for some reason (this should not be needed in most cases).
+     *
+     * @param groupIfName Group interface name to use.
+     * @param goDeviceAddress MAC address of the group owner device.
+     * @param peerAddress MAC address of the device to invite.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void invite(in String groupIfName, in byte[] goDeviceAddress, in byte[] peerAddress);
+
+    /**
+     * Retrieve a list of all the network Id's controlled by the supplicant.
+     *
+     * The corresponding |ISupplicantP2pNetwork| object for any network can be
+     * retrieved using the |getNetwork| method.
+     *
+     * @return List of all network Id's controlled by the supplicant.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     */
+    int[] listNetworks();
+
+    /**
+     * Send P2P provision discovery request to the specified peer. The
+     * parameters for this command are the P2P device address of the peer and the
+     * desired configuration method.
+     *
+     * @param peerAddress MAC address of the device to send discovery.
+     * @method provisionMethod Provisioning method to use.
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void provisionDiscovery(in byte[] peerAddress, in WpsProvisionMethod provisionMethod);
+
+    /**
+     * Register for callbacks from this interface.
+     *
+     * These callbacks are invoked for events that are specific to this interface.
+     * Registration of multiple callback objects is supported. These objects must
+     * be automatically deleted when the corresponding client process is dead or
+     * if this interface is removed.
+     *
+     * @param callback An instance of the |ISupplicantP2pIfaceCallback| AIDL
+     *        interface object.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void registerCallback(in ISupplicantP2pIfaceCallback callback);
+
+    /**
+     * Reinvoke a device from a persistent group.
+     *
+     * @param persistentNetworkId Used to specify the persistent group.
+     * @param peerAddress MAC address of the device to reinvoke.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void reinvoke(in int persistentNetworkId, in byte[] peerAddress);
+
+    /**
+     * Reject connection attempt from a peer (specified with a device
+     * address). This is a mechanism to reject a pending group owner negotiation
+     * with a peer and request to automatically block any further connection or
+     * discovery of the peer.
+     *
+     * @param peerAddress MAC address of the device to reject.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     *         |SupplicantStatusCode.FAILURE_IFACE_DISABLED|
+     */
+    void reject(in byte[] peerAddress);
+
+    /**
+     * This command can be used to remove a bonjour service.
+     *
+     * @param query Hex dump of the query data.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NOT_STARTED|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void removeBonjourService(in byte[] query);
+
+    /**
+     * Terminate a P2P group. If a new virtual network interface was used for
+     * the group, it must also be removed. The network interface name of the
+     * group interface is used as a parameter for this command.
+     *
+     * @param groupIfName Group interface name to use.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void removeGroup(in String groupIfName);
+
+    /**
+     * Remove a network from the interface.
+     *
+     * Use |ISupplicantP2pNetwork.getId()| on the corresponding network AIDL
+     * interface object to retrieve the ID.
+     *
+     * @param id Network ID allocated to the corresponding network.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_UNKNOWN|
+     */
+    void removeNetwork(in int id);
+
+    /**
+     * This command can be used to remove a UPNP service.
+     *
+     * @param version Version to be used.
+     * @package serviceName Service name to be used.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NOT_STARTED|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void removeUpnpService(in int version, in String serviceName);
+
+    /**
+     * Report the initiation of the NFC handover select.
+     *
+     * @param select Bytes representing the handover select as specified in
+     *        section 3.1.2 of NFC Connection Handover 1.2 Technical
+     *        Specification.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void reportNfcHandoverInitiation(in byte[] select);
+
+    /**
+     * Report the response of the NFC handover request.
+     *
+     * @param request Bytes representing the handover request as specified in
+     *        section 3.1.1 of NFC Connection Handover 1.2 Technical
+     *        Specification.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void reportNfcHandoverResponse(in byte[] request);
+
+    /**
+     * Schedule a P2P service discovery request. The parameters for this command
+     * are the device address of the peer device (or 00:00:00:00:00:00 for
+     * wildcard query that is sent to every discovered P2P peer that supports
+     * service discovery) and P2P Service Query TLV(s) as hexdump.
+     *
+     * @param peerAddress MAC address of the device to discover.
+     * @param query Hex dump of the query data.
+     * @return Identifier for the request. Can be used to cancel the
+     *         request.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    long requestServiceDiscovery(in byte[] peerAddress, in byte[] query);
+
+    /**
+     * Persist the current configuration to disk.
+     *
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void saveConfig();
+
+    /**
+     * Set P2P disallowed frequency ranges.
+     *
+     * Specify ranges of frequencies that are disallowed for any P2P operations.
+     *
+     * @param ranges List of ranges which needs to be disallowed.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void setDisallowedFrequencies(in FreqRange[] ranges);
+
+    /**
+     * Set whether to enable EDMG(802.11ay). Only allowed if hw mode is |HOSTAPD_MODE_IEEE80211AD|
+     *
+     * @param enable true to set, false otherwise.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setEdmg(in boolean enable);
+
+    /**
+     * Set the Maximum idle time in seconds for P2P groups.
+     * This value controls how long a P2P group is maintained after there
+     * is no other members in the group. As a group owner, this means no
+     * associated stations in the group. As a P2P client, this means no
+     * group owner seen in scan results.
+     *
+     * @param groupIfName Group interface name to use.
+     * @param timeoutInSec Timeout value in seconds.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void setGroupIdle(in String groupIfName, in int timeoutInSec);
+
+    /**
+     * Set P2P Listen channel.
+     *
+     * When specifying a social channel on the 2.4 GHz band (1/6/11) there is no
+     * need to specify the operating class since it defaults to 81. When
+     * specifying a social channel on the 60 GHz band (2), specify the 60 GHz
+     * operating class (180).
+     *
+     * @param channel Wifi channel. eg, 1, 6, 11.
+     * @param operatingClass Operating Class indicates the channel set of the AP
+     *        indicated by this BSSID
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void setListenChannel(in int channel, in int operatingClass);
+
+    /**
+     * Set MAC randomization enabled/disabled.
+     *
+     * @param enable true to enable, false to disable.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void setMacRandomization(in boolean enable);
+
+    /**
+     * Send driver command to set Miracast mode.
+     *
+     * @param mode Mode of Miracast.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void setMiracastMode(in MiracastMode mode);
+
+    /**
+     * Turn on/off power save mode for the interface.
+     *
+     * @param groupIfName Group interface name to use.
+     * @param enable Indicate if power save is to be turned on/off.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_DISABLED|
+     */
+    void setPowerSave(in String groupIfName, in boolean enable);
+
+    /**
+     * Set the postfix to be used for P2P SSID's.
+     *
+     * @param postfix String to be appended to SSID.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void setSsidPostfix(in byte[] postfix);
+
+    /**
+     * Set Wifi Display device info.
+     *
+     * @param info WFD device info as described in section 5.1.2 of WFD technical
+     *        specification v1.0.0.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void setWfdDeviceInfo(in byte[] info);
+
+    /**
+     * Set Wifi Display R2 device info.
+     *
+     * @param info WFD R2 device info as described in section 5.1.12 of WFD technical
+     *        specification v2.1.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void setWfdR2DeviceInfo(in byte[] info);
+
+    /**
+     * Set the list of supported config methods for WPS operations.
+     *
+     * @param configMethods Mask of WPS configuration methods supported by the
+     *        device.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     */
+    void setWpsConfigMethods(in WpsConfigMethods configMethods);
+
+    /**
+     * Set the device name for WPS operations.
+     * User-friendly description of device (up to |WPS_DEVICE_NAME_MAX_LEN|
+     * octets encoded in UTF-8).
+     *
+     * @param name Name to be set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     */
+    void setWpsDeviceName(in String name);
+
+    /**
+     * Set the device type for WPS operations.
+     *
+     * @param type Type of device. Refer to section B.1 of Wifi P2P
+     *       Technical specification v1.2.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     */
+    void setWpsDeviceType(in byte[] type);
+
+    /**
+     * Set the manufacturer for WPS operations.
+     * The manufacturer of the device (up to |WPS_MANUFACTURER_MAX_LEN| ASCII
+     * characters).
+     *
+     * @param manufacturer Manufacture to be set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     */
+    void setWpsManufacturer(in String manufacturer);
+
+    /**
+     * Set the model name for WPS operations.
+     * Model of the device (up to |WPS_MODEL_NAME_MAX_LEN| ASCII characters).
+     *
+     * @param modelName Model name to be set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     */
+    void setWpsModelName(in String modelName);
+
+    /**
+     * Set the model number for WPS operations.
+     * Additional device description (up to |WPS_MODEL_NUMBER_MAX_LEN| ASCII
+     * characters).
+     *
+     * @param modelNumber Model number to be set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     */
+    void setWpsModelNumber(in String modelNumber);
+
+    /**
+     * Set the serial number for WPS operations.
+     * Serial number of the device (up to |WPS_SERIAL_NUMBER_MAX_LEN| characters)
+     *
+     * @param serialNumber Serial number to be set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     */
+    void setWpsSerialNumber(in String serialNumber);
+
+    /**
+     * Initiate WPS Push Button setup.
+     * The PBC operation requires that a button is also pressed at the
+     * AP/Registrar at about the same time (2 minute window).
+     *
+     * @param groupIfName Group interface name to use.
+     * @param bssid BSSID of the AP. Use zero'ed bssid to indicate wildcard.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void startWpsPbc(in String groupIfName, in byte[] bssid);
+
+    /**
+     * Initiate WPS Pin Display setup.
+     *
+     * @param groupIfName Group interface name to use.
+     * @param bssid BSSID of the AP. Use zero'ed bssid to indicate wildcard.
+     * @return 8 digit pin generated.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    String startWpsPinDisplay(in String groupIfName, in byte[] bssid);
+
+    /**
+     * Initiate WPS Pin Keypad setup.
+     *
+     * @param groupIfName Group interface name to use.
+     * @param pin 8 digit pin to be used.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void startWpsPinKeypad(in String groupIfName, in String pin);
+
+    /**
+     * Stop an ongoing P2P service discovery.
+     *
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     *         |SupplicantStatusCode.FAILURE_IFACE_DISABLED|
+     */
+    void stopFind();
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pIfaceCallback.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pIfaceCallback.aidl
new file mode 100644
index 0000000..f0cabd6
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pIfaceCallback.aidl
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+import android.hardware.wifi.supplicant.P2pGroupCapabilityMask;
+import android.hardware.wifi.supplicant.P2pProvDiscStatusCode;
+import android.hardware.wifi.supplicant.P2pStatusCode;
+import android.hardware.wifi.supplicant.WpsConfigMethods;
+import android.hardware.wifi.supplicant.WpsDevPasswordId;
+
+/**
+ * Callback Interface exposed by the supplicant service
+ * for each P2P mode interface (ISupplicantP2pIface).
+ *
+ * Clients need to host an instance of this AIDL interface object and
+ * pass a reference of the object to the supplicant via the
+ * corresponding |ISupplicantP2pIface.registerCallback| method.
+ */
+@VintfStability
+interface ISupplicantP2pIfaceCallback {
+    /**
+     * Used to indicate that a P2P device has been found.
+     *
+     * @param srcAddress MAC address of the device found. This must either
+     *        be the P2P device address or the P2P interface address.
+     * @param p2pDeviceAddress P2P device address.
+     * @param primaryDeviceType Type of device. Refer to section B.1 of Wifi P2P
+     *        Technical specification v1.2.
+     * @param deviceName Name of the device.
+     * @param configMethods Mask of WPS configuration methods supported by the
+     *        device.
+     * @param deviceCapabilities Refer to section 4.1.4 of Wifi P2P Technical
+     *        specification v1.2.
+     * @param groupCapabilites Refer to section 4.1.4 of Wifi P2P Technical
+     *        specification v1.2.
+     * @param wfdDeviceInfo WFD device info as described in section 5.1.2 of WFD
+     *        technical specification v1.0.0.
+     */
+    oneway void onDeviceFound(in byte[] srcAddress, in byte[] p2pDeviceAddress,
+            in byte[] primaryDeviceType, in String deviceName, in WpsConfigMethods configMethods,
+            in byte deviceCapabilities, in P2pGroupCapabilityMask groupCapabilities,
+            in byte[] wfdDeviceInfo);
+
+    /**
+     * Used to indicate that a P2P device has been lost.
+     *
+     * @param p2pDeviceAddress P2P device address.
+     */
+    oneway void onDeviceLost(in byte[] p2pDeviceAddress);
+
+    /**
+     * Used to indicate the termination of P2P find operation.
+     */
+    oneway void onFindStopped();
+
+    /**
+     * Used to indicate the completion of a P2P Group Owner negotiation request.
+     *
+     * @param status Status of the GO negotiation.
+     */
+    oneway void onGoNegotiationCompleted(in P2pStatusCode status);
+
+    /**
+     * Used to indicate the reception of a P2P Group Owner negotiation request.
+     *
+     * @param srcAddress MAC address of the device that initiated the GO
+     *        negotiation request.
+     * @param passwordId Type of password.
+     */
+    oneway void onGoNegotiationRequest(in byte[] srcAddress, in WpsDevPasswordId passwordId);
+
+    /**
+     * Used to indicate a failure to form a P2P group.
+     *
+     * @param failureReason Failure reason string for debug purposes.
+     */
+    oneway void onGroupFormationFailure(in String failureReason);
+
+    /**
+     * Used to indicate a successful formation of a P2P group.
+     */
+    oneway void onGroupFormationSuccess();
+
+    /**
+     * Used to indicate the removal of a P2P group.
+     *
+     * @param groupIfName Interface name of the group. (For ex: p2p-p2p0-1)
+     * @param isGroupOwner Whether this device is owner of the group.
+     */
+    oneway void onGroupRemoved(in String groupIfname, in boolean isGroupOwner);
+
+    /**
+     * Used to indicate the start of a P2P group.
+     *
+     * @param groupIfName Interface name of the group. (For ex: p2p-p2p0-1)
+     * @param isGroupOwner Whether this device is owner of the group.
+     * @param ssid SSID of the group.
+     * @param frequency Frequency on which this group is created.
+     * @param psk PSK used to secure the group.
+     * @param passphrase PSK passphrase used to secure the group.
+     * @param goDeviceAddress MAC Address of the owner of this group.
+     * @param isPersistent Whether this group is persisted or not.
+     */
+    oneway void onGroupStarted(in String groupIfname, in boolean isGroupOwner, in byte[] ssid,
+            in int frequency, in byte[] psk, in String passphrase, in byte[] goDeviceAddress,
+            in boolean isPersistent);
+
+    /**
+     * Used to indicate the reception of a P2P invitation.
+     *
+     * @param srcAddress MAC address of the device that sent the invitation.
+     * @param goDeviceAddress MAC Address of the owner of this group.
+     * @param bssid Bssid of the group.
+     * @param persistentNetworkId Persistent network Id of the group.
+     * @param operatingFrequency Frequency on which the invitation was received.
+     */
+    oneway void onInvitationReceived(in byte[] srcAddress, in byte[] goDeviceAddress,
+            in byte[] bssid, in int persistentNetworkId, in int operatingFrequency);
+
+    /**
+     * Used to indicate the result of the P2P invitation request.
+     *
+     * @param bssid Bssid of the group.
+     * @param status Status of the invitation.
+     */
+    oneway void onInvitationResult(in byte[] bssid, in P2pStatusCode status);
+
+    /**
+     * Used to indicate the completion of a P2P provision discovery request.
+     *
+     * @param p2pDeviceAddress P2P device address.
+     * @param isRequest Whether we received or sent the provision discovery.
+     * @param status Status of the provision discovery.
+     * @param configMethods Mask of WPS configuration methods supported.
+     * @param generatedPin 8 digit pin generated.
+     */
+    oneway void onProvisionDiscoveryCompleted(in byte[] p2pDeviceAddress, in boolean isRequest,
+            in P2pProvDiscStatusCode status, in WpsConfigMethods configMethods,
+            in String generatedPin);
+
+    /**
+     * Used to indicate that a P2P Wi-Fi Display R2 device has been found. Refer to
+     * Wi-Fi Display Technical Specification Version 2.0.
+     *
+     * @param srcAddress MAC address of the device found. This must either
+     *        be the P2P device address for a peer which is not in a group,
+     *        or the P2P interface address for a peer which is a Group Owner.
+     * @param p2pDeviceAddress P2P device address.
+     * @param primaryDeviceType Type of device. Refer to section B.1 of Wifi P2P
+     *        Technical specification v1.2.
+     * @param deviceName Name of the device.
+     * @param configMethods Mask of WPS configuration methods supported by the
+     *        device.
+     * @param deviceCapabilities Refer to section 4.1.4 of Wifi P2P Technical
+     *        specification v1.2.
+     * @param groupCapabilites Refer to section 4.1.4 of Wifi P2P Technical
+     *        specification v1.2.
+     * @param wfdDeviceInfo WFD device info as described in section 5.1.2 of WFD
+     *        technical specification v1.0.0.
+     * @param wfdR2DeviceInfo WFD R2 device info as described in section 5.1.12 of WFD
+     *        technical specification v2.1.
+     */
+    oneway void onR2DeviceFound(in byte[] srcAddress, in byte[] p2pDeviceAddress,
+            in byte[] primaryDeviceType, in String deviceName, in WpsConfigMethods configMethods,
+            in byte deviceCapabilities, in P2pGroupCapabilityMask groupCapabilities,
+            in byte[] wfdDeviceInfo, in byte[] wfdR2DeviceInfo);
+
+    /**
+     * Used to indicate the reception of a P2P service discovery response.
+     *
+     * @param srcAddress MAC address of the device that sent the service discovery.
+     * @param updateIndicator Service update indicator. Refer to section 3.1.3 of
+     *        Wifi P2P Technical specification v1.2.
+     * @parm tlvs Refer to section 3.1.3.1 of Wifi P2P Technical specification v1.2.
+     */
+    oneway void onServiceDiscoveryResponse(
+            in byte[] srcAddress, in char updateIndicator, in byte[] tlvs);
+
+    /**
+     * Used to indicate when a STA device is connected to this device.
+     *
+     * @param srcAddress MAC address of the device that was authorized.
+     * @param p2pDeviceAddress P2P device address.
+     */
+    oneway void onStaAuthorized(in byte[] srcAddress, in byte[] p2pDeviceAddress);
+
+    /**
+     * Used to indicate when a STA device is disconnected from this device.
+     *
+     * @param srcAddress MAC address of the device that was deauthorized.
+     * @param p2pDeviceAddress P2P device address.
+     */
+    oneway void onStaDeauthorized(in byte[] srcAddress, in byte[] p2pDeviceAddress);
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pNetwork.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pNetwork.aidl
new file mode 100644
index 0000000..f037252
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pNetwork.aidl
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+import android.hardware.wifi.supplicant.IfaceType;
+import android.hardware.wifi.supplicant.MacAddress;
+
+/**
+ * Interface exposed by the supplicant for each P2P mode network
+ * configuration it controls.
+ */
+@VintfStability
+interface ISupplicantP2pNetwork {
+    /**
+     * Get the BSSID set for this network.
+     *
+     * @return bssid Value set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    byte[] getBssid();
+
+    /**
+     * Get the list of P2P Clients in a persistent group (GO).
+     * This is a list of P2P Clients (P2P Device Address) that have joined
+     * the persistent group. This is maintained on the GO for persistent
+     * group entries (disabled == 2).
+     *
+     * @return MAC addresses of the clients.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantP2ptusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    MacAddress[] getClientList();
+
+    /**
+     * Retrieves the ID allocated to this network by the supplicant.
+     *
+     * This is not the |SSID| of the network, but an internal identifier for
+     * this network used by the supplicant.
+     *
+     * @return Network ID.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    int getId();
+
+    /**
+     * Retrieves the name of the interface this network belongs to.
+     *
+     * @return Name of the network interface, e.g., wlan0
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    String getInterfaceName();
+
+    /**
+     * Getters for the various network params.
+     *
+     *
+     * Get SSID for this network.
+     *
+     * @return ssid value set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    byte[] getSsid();
+
+    /**
+     * Retrieves the type of the interface this network belongs to.
+     *
+     * @return Type of the network interface, e.g., STA.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    IfaceType getType();
+
+    /**
+     * Check if the network is currently active one.
+     *
+     * @return true if current, false otherwise.
+     * @throws ServiceSpecificException with one of the following values:,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    boolean isCurrent();
+
+    /**
+     * Check if the device is the group owner of the network.
+     *
+     * @return true if group owner, false otherwise.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    boolean isGroupOwner();
+
+    /**
+     * Check if the network is marked persistent.
+     *
+     * @return true if persistent, false otherwise.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    boolean isPersistent();
+
+    /**
+     * Set the list of P2P Clients in a persistent group (GO).
+     * This is a list of P2P Clients (P2P Device Address) that have joined
+     * the persistent group. This is maintained on the GO for persistent
+     * group entries (disabled == 2).
+     *
+     * @param clients MAC address of the clients.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantP2ptusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setClientList(in MacAddress[] clients);
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl
new file mode 100644
index 0000000..5cb236f
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIface.aidl
@@ -0,0 +1,715 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+import android.hardware.wifi.supplicant.AnqpInfoId;
+import android.hardware.wifi.supplicant.BtCoexistenceMode;
+import android.hardware.wifi.supplicant.ConnectionCapabilities;
+import android.hardware.wifi.supplicant.DppAkm;
+import android.hardware.wifi.supplicant.DppCurve;
+import android.hardware.wifi.supplicant.DppNetRole;
+import android.hardware.wifi.supplicant.DppResponderBootstrapInfo;
+import android.hardware.wifi.supplicant.Hs20AnqpSubtypes;
+import android.hardware.wifi.supplicant.ISupplicantStaIfaceCallback;
+import android.hardware.wifi.supplicant.ISupplicantStaNetwork;
+import android.hardware.wifi.supplicant.IfaceType;
+import android.hardware.wifi.supplicant.KeyMgmtMask;
+import android.hardware.wifi.supplicant.RxFilterType;
+import android.hardware.wifi.supplicant.WpaDriverCapabilitiesMask;
+import android.hardware.wifi.supplicant.WpsConfigMethods;
+
+/**
+ * Interface exposed by the supplicant for each station mode network
+ * interface (e.g wlan0) it controls.
+ */
+@VintfStability
+interface ISupplicantStaIface {
+    /**
+     * Add a DPP peer URI. URI is acquired externally, e.g. by scanning a QR code
+     *
+     * @param uri Peer's DPP URI.
+     * @return ID for the URI
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    int addDppPeerUri(in String uri);
+
+    /**
+     * External programs can request supplicant to not start offchannel
+     * operations during other tasks that may need exclusive control of the
+     * radio.
+     *
+     * This method can be used to reserve a slot for radio access. If freq is
+     * specified, other radio work items on the same channel can be completed in
+     * parallel. Otherwise, all other radio work items are blocked during
+     * execution. Timeout must be set to |ExtRadioWorkDefaults.TIMEOUT_IN_SECS|
+     * seconds by default to avoid blocking supplicant operations on the iface
+     * for excessive time. If a longer (or shorter) safety timeout is needed,
+     * that may be specified with the optional timeout parameter. This command
+     * returns an identifier for the radio work item.
+     *
+     * Once the radio work item has been started,
+     * |ISupplicant.onExtRadioWorkStart| callback is indicated that the external
+     * processing can start.
+     *
+     * @param name Name for the radio work being added.
+     * @param freqInMhz Frequency to specify. Set to 0 for all channels.
+     * @param timeoutInSec Timeout to specify. Set to 0 for default timeout.
+     * @return Identifier for this radio work.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     */
+    int addExtRadioWork(in String name, in int freqInMhz, in int timeoutInSec);
+
+    /**
+     * Add a new network to the interface.
+     *
+     * @return AIDL interface object representing the new network if
+     *         successful, null otherwise.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    @PropagateAllowBlocking ISupplicantStaNetwork addNetwork();
+
+    /**
+     * Send driver command to add the specified RX filter.
+     *
+     * @param type Type of filter.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void addRxFilter(in RxFilterType type);
+
+    /**
+     * Cancel any ongoing WPS operations.
+     *
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void cancelWps();
+
+    /**
+     * Disconnect from the current active network.
+     *
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_DISABLED|
+     */
+    void disconnect();
+
+    /**
+     * Enable/Disable auto reconnect to networks.
+     * Use this to prevent wpa_supplicant from trying to connect to networks
+     * on its own.
+     *
+     * @param enable true to enable, false to disable.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_DISABLED|
+     */
+    void enableAutoReconnect(in boolean enable);
+
+    /**
+     * Add fast initial link setup (IEEE 802.11ai FILS) HLP packets.
+     * Use this to add higher layer protocol (HLP) packet in FILS (Re)Association Request frame
+     * (Eg: DHCP discover packet).
+     *
+     * @param dst_mac MAC address of the destination
+     * @param pkt The contents of the HLP packet starting from ethertype
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_DISABLED|
+     */
+    void filsHlpAddRequest(in byte[] dst_mac, in byte[] pkt);
+
+    /**
+     * Flush fast initial link setup (IEEE 802.11ai FILS) HLP packets.
+     * Use this to flush all the higher layer protocol (HLP) packets added in
+     * wpa_supplicant to send in FILS (Re)Association Request frame
+     * (Eg: DHCP discover packet).
+     *
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_DISABLED|
+     */
+    void filsHlpFlushRequest();
+
+    /**
+     * Generates DPP bootstrap information: Bootstrap ID, DPP URI and listen
+     * channel for responder mode.
+     *
+     * @param macAddress MAC address of the interface for the DPP operation.
+     * @param deviceInfo Device specific information.
+     *        As per DPP Specification V1.0 section 5.2,
+     *        allowed Range of ASCII characters in deviceInfo - %x20-7E
+     *        semicolon is not allowed.
+     * @param curve Elliptic curve cryptography type used to generate DPP
+     *        public/private key pair.
+     * @return Bootstrap info.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     *         |SupplicantStatusCode.FAILURE_UNSUPPORTED|
+     */
+    DppResponderBootstrapInfo generateDppBootstrapInfoForResponder(
+            in byte[] macAddress, in String deviceInfo, in DppCurve curve);
+
+    /**
+     * Get Connection capabilities
+     *
+     * @return Connection capabilities.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     */
+    ConnectionCapabilities getConnectionCapabilities();
+
+    /**
+     * Get Key management capabilities of the device
+     *
+     * @return Bitmap of key management mask.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     */
+    KeyMgmtMask getKeyMgmtCapabilities();
+
+    /**
+     * Send driver command to get MAC address of the device.
+     *
+     * @return MAC address of the device.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    byte[] getMacAddress();
+
+    /**
+     * Retrieves the name of the network interface.
+     *
+     * @return Name of the network interface, e.g., wlan0
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    String getName();
+
+    /**
+     * Gets an AIDL interface object for the network corresponding to the
+     * network id.
+     *
+     * Use |ISupplicantStaNetwork.getId()| on the corresponding network AIDL
+     * interface object to retrieve the ID.
+     *
+     * @param id Network ID allocated to the corresponding network.
+     * @return AIDL interface object representing the new network if
+     *         successful, null otherwise.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_UNKNOWN|
+     */
+    @PropagateAllowBlocking ISupplicantStaNetwork getNetwork(in int id);
+
+    /**
+     * Retrieves the type of the network interface.
+     *
+     * @return Type of the network interface, e.g., STA.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    IfaceType getType();
+
+    /**
+     * Get wpa driver capabilities.
+     *
+     * @return Bitmap of wpa driver features.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     */
+    WpaDriverCapabilitiesMask getWpaDriverCapabilities();
+
+    /**
+     * Initiate ANQP (for IEEE 802.11u Interworking/Hotspot 2.0) queries with the
+     * specified access point.
+     * The ANQP data fetched must be returned in the
+     * |ISupplicantStaIfaceCallback.onAnqpQueryDone| callback.
+     *
+     * @param macAddress MAC address of the access point.
+     * @param infoElements List of information elements to query for.
+     * @param subtypes List of HS20 subtypes to query for.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void initiateAnqpQuery(
+            in byte[] macAddress, in AnqpInfoId[] infoElements, in Hs20AnqpSubtypes[] subTypes);
+
+    /**
+     * Initiate the Hotspot 2.0 icon query with the specified accesss point.
+     * The icon data fetched must be returned in the
+     * |ISupplicantStaIfaceCallback.onHs20IconQueryDone| callback.
+     *
+     * @param macAddress MAC address of the access point.
+     * @param fileName Name of the file to request from the access point.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void initiateHs20IconQuery(in byte[] macAddress, in String fileName);
+
+    /**
+     * Initiate TDLS discover with the provided peer MAC address.
+     *
+     * @param macAddress MAC address of the peer.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void initiateTdlsDiscover(in byte[] macAddress);
+
+    /**
+     * Initiate TDLS setup with the provided peer MAC address.
+     *
+     * @param macAddress MAC address of the peer.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void initiateTdlsSetup(in byte[] macAddress);
+
+    /**
+     * Initiate TDLS teardown with the provided peer MAC address.
+     *
+     * @param macAddress MAC address of the peer.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void initiateTdlsTeardown(in byte[] macAddress);
+
+    /**
+     * Initiate Venue URL ANQP (for IEEE 802.11u Interworking/Hotspot 2.0) query with the
+     * specified access point. This specific query can be used only post connection, once security
+     * is established and PMF is enabled, to avoid spoofing preassociation ANQP responses.
+     * The ANQP data fetched must be returned in the
+     * |ISupplicantStaIfaceCallback.onAnqpQueryDone| callback.
+     *
+     * @param macAddress MAC address of the access point.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void initiateVenueUrlAnqpQuery(in byte[] macAddress);
+
+    /**
+     * Retrieve a list of all the network Id's controlled by the supplicant.
+     *
+     * The corresponding |ISupplicantStaNetwork| object for any network can be
+     * retrieved using |getNetwork| method.
+     *
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     * @return List of all network Id's controlled by the supplicant.
+     */
+    int[] listNetworks();
+
+    /**
+     * Reconnect to the currently active network, even if we are already
+     * connected.
+     *
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_DISABLED|
+     */
+    void reassociate();
+
+    /**
+     * Reconnect to the currently active network, if we are currently
+     * disconnected.
+     *
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_DISABLED|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_NOT_DISCONNECTED|
+     */
+    void reconnect();
+
+    /**
+     * Register for callbacks from this interface.
+     *
+     * These callbacks are invoked for events that are specific to this interface.
+     * Registration of multiple callback objects is supported. These objects must
+     * be automatically deleted when the corresponding client process is dead or
+     * if this interface is removed.
+     *
+     * @param callback An instance of the |ISupplicantStaIfaceCallback| AIDL
+     *        interface object.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void registerCallback(in ISupplicantStaIfaceCallback callback);
+
+    /**
+     * Remove a DPP peer URI.
+     *
+     * @param id The ID of the URI, as returned by |addDppPeerUri|.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void removeDppUri(in int id);
+
+    /**
+     * Indicates to supplicant that the external radio work has completed.
+     * This allows other radio works to be performed. If this method is not
+     * invoked (e.g., due to the external program terminating), supplicant
+     * must time out the radio work item on the iface and send
+     * |ISupplicantCallback.onExtRadioWorkTimeout| event to indicate
+     * that this has happened.
+     *
+     * This method may also be used to cancel items that have been scheduled
+     * via |addExtRadioWork|, but have not yet been started (notified via
+     * |ISupplicantCallback.onExtRadioWorkStart|).
+     *
+     * @param id Identifier generated for the radio work addition
+     *         (using |addExtRadioWork|).
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     */
+    void removeExtRadioWork(in int id);
+
+    /**
+     * Remove a network from the interface.
+     *
+     * Use |ISupplicantStaNetwork.getId()| on the corresponding network AIDL
+     * interface object to retrieve the ID.
+     *
+     * @param id Network ID allocated to the corresponding network.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_UNKNOWN|
+     */
+    void removeNetwork(in int id);
+
+    /**
+     * Send driver command to remove the specified RX filter.
+     *
+     * @param type Type of filter.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void removeRxFilter(in RxFilterType type);
+
+    /**
+     * Send driver command to set Bluetooth coexistence mode.
+     *
+     * @param mode Mode of Bluetooth coexistence.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void setBtCoexistenceMode(in BtCoexistenceMode mode);
+
+    /**
+     * Send driver command to set Bluetooth coexistence scan mode.
+     * When this mode is on, some of the low-level scan parameters
+     * used by the driver are changed to reduce interference
+     * with A2DP streaming.
+     *
+     * @param enable true to enable, false to disable.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void setBtCoexistenceScanModeEnabled(in boolean enable);
+
+    /**
+     * Send driver command to set country code.
+     *
+     * @param code 2 byte country code (as defined in ISO 3166) to set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void setCountryCode(in byte[] code);
+
+    /**
+     * Use external processing for SIM/USIM operations
+     *
+     * @param useExternalSim true to use external, false otherwise.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void setExternalSim(in boolean useExternalSim);
+
+    /**
+     * Set Wi-Fi Alliance Agile Multiband (MBO) cellular data status.
+     *
+     * @param available true means cellular data available, false otherwise.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     */
+    void setMboCellularDataStatus(in boolean available);
+
+    /**
+     * Turn on/off power save mode for the interface.
+     *
+     * @param enable Indicate if power save is to be turned on/off.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_DISABLED|
+     */
+    void setPowerSave(in boolean enable);
+
+    /**
+     * Send driver command to set suspend optimizations for power save.
+     *
+     * @param enable true to enable, false to disable.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void setSuspendModeEnabled(in boolean enable);
+
+    /**
+     * Set the list of supported config methods for WPS operations.
+     *
+     * @param configMethods Mask of WPS configuration methods supported by the
+     *        device.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     */
+    void setWpsConfigMethods(in WpsConfigMethods configMethods);
+
+    /**
+     * Set the device name for WPS operations.
+     * User-friendly description of device (up to |WPS_DEVICE_NAME_MAX_LEN|
+     * octets encoded in UTF-8).
+     *
+     * @parm name Name to be set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     */
+    void setWpsDeviceName(in String name);
+
+    /**
+     * Set the device type for WPS operations.
+     *
+     * @parm type Type of device. Refer to section B.1 of Wifi P2P
+     *       Technical specification v1.2.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     */
+    void setWpsDeviceType(in byte[] type);
+
+    /**
+     * Set the manufacturer for WPS operations.
+     * The manufacturer of the device (up to |WPS_MANUFACTURER_MAX_LEN| ASCII
+     * characters).
+     *
+     * @parm manufacturer Manufacture to be set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     */
+    void setWpsManufacturer(in String manufacturer);
+
+    /**
+     * Set the model name for WPS operations.
+     * Model of the device (up to |WPS_MODEL_NAME_MAX_LEN| ASCII characters).
+     *
+     * @parm modelName Model name to be set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     */
+    void setWpsModelName(in String modelName);
+
+    /**
+     * Set the model number for WPS operations.
+     * Additional device description (up to |WPS_MODEL_NUMBER_MAX_LEN| ASCII
+     * characters).
+     *
+     * @parm modelNumber Model number to be set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     */
+    void setWpsModelNumber(in String modelNumber);
+
+    /**
+     * Set the serial number for WPS operations.
+     * Serial number of the device (up to |WPS_SERIAL_NUMBER_MAX_LEN| characters)
+     *
+     * @parm serialNumber Serial number to be set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     */
+    void setWpsSerialNumber(in String serialNumber);
+
+    /**
+     * Start DPP in Configurator-Initiator mode.
+     *
+     * @param peerBootstrapId Peer device's URI ID.
+     * @param ownBootstrapId Local device's URI ID (0 for none, optional).
+     * @param ssid Network SSID to send to peer (SAE/PSK mode).
+     * @param password Network password to send to peer (SAE/PSK mode).
+     * @param psk Network PSK to send to peer (PSK mode only). Either password or psk should be set.
+     * @param netRole Role to configure the peer, |DppNetRole.DPP_NET_ROLE_STA| or
+     *        |DppNetRole.DPP_NET_ROLE_AP|.
+     * @param securityAkm Security AKM to use (See DppAkm).
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void startDppConfiguratorInitiator(in int peerBootstrapId, in int ownBootstrapId,
+            in String ssid, in String password, in String psk, in DppNetRole netRole,
+            in DppAkm securityAkm);
+
+    /**
+     * Start DPP in Enrollee-Initiator mode.
+     *
+     * @param peerBootstrapId Peer device's URI ID.
+     * @param ownBootstrapId Local device's URI ID (0 for none, optional).
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void startDppEnrolleeInitiator(in int peerBootstrapId, in int ownBootstrapId);
+
+    /**
+     * Start DPP in Enrollee-Responder mode.
+     * Framework must first call |generateDppBootstrapInfoForResponder| to generate
+     * the bootstrapping information: Bootstrap ID, DPP URI and the listen channel.
+     * Then call this API with derived listen channel to start listening for
+     * authentication request from Peer initiator.
+     *
+     * @param listenChannel DPP listen channel.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     *         |SupplicantStatusCode.FAILURE_UNSUPPORTED|
+     */
+    void startDppEnrolleeResponder(in int listenChannel);
+
+    /**
+     * Send driver command to start RX filter.
+     *
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void startRxFilter();
+
+    /**
+     * Initiate WPS Push Button setup.
+     * The PBC operation requires that a button is also pressed at the
+     * AP/Registrar at about the same time (2 minute window).
+     *
+     * @param bssid BSSID of the AP. Use zero'ed bssid to indicate wildcard.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void startWpsPbc(in byte[] bssid);
+
+    /**
+     * Initiate WPS Pin Display setup.
+     *
+     * @param bssid BSSID of the AP. Use zero'ed bssid to indicate wildcard.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     * @return 8 digit pin generated.
+     */
+    String startWpsPinDisplay(in byte[] bssid);
+
+    /**
+     * Initiate WPS Pin Keypad setup.
+     *
+     * @param pin 8 digit pin to be used.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void startWpsPinKeypad(in String pin);
+
+    /**
+     * Initiate WPS setup in registrar role to learn the current AP configuration.
+     *
+     * @param bssid BSSID of the AP.
+     * @param pin Pin of the AP.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void startWpsRegistrar(in byte[] bssid, in String pin);
+
+    /**
+     * Stop DPP Initiator operation.
+     *
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void stopDppInitiator();
+
+    /**
+     * Stop DPP Responder operation - Remove the bootstrap code and stop listening.
+     *
+     * @param ownBootstrapId Local device's URI ID obtained through
+     *        |generateDppBootstrapInfoForResponder| call.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     *         |SupplicantStatusCode.FAILURE_UNSUPPORTED|
+     */
+    void stopDppResponder(in int ownBootstrapId);
+
+    /**
+     * Send driver command to stop RX filter.
+     *
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    void stopRxFilter();
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
new file mode 100644
index 0000000..594fef9
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+import android.hardware.wifi.supplicant.AnqpData;
+import android.hardware.wifi.supplicant.AssociationRejectionData;
+import android.hardware.wifi.supplicant.BssTmData;
+import android.hardware.wifi.supplicant.BssidChangeReason;
+import android.hardware.wifi.supplicant.DppAkm;
+import android.hardware.wifi.supplicant.DppEventType;
+import android.hardware.wifi.supplicant.DppFailureCode;
+import android.hardware.wifi.supplicant.DppProgressCode;
+import android.hardware.wifi.supplicant.Hs20AnqpData;
+import android.hardware.wifi.supplicant.OsuMethod;
+import android.hardware.wifi.supplicant.StaIfaceCallbackState;
+import android.hardware.wifi.supplicant.StaIfaceReasonCode;
+import android.hardware.wifi.supplicant.WpsConfigError;
+import android.hardware.wifi.supplicant.WpsErrorIndication;
+
+/**
+ * Callback Interface exposed by the supplicant service
+ * for each station mode interface (ISupplicantStaIface).
+ *
+ * Clients need to host an instance of this AIDL interface object and
+ * pass a reference of the object to the supplicant via the
+ * corresponding |ISupplicantStaIface.registerCallback| method.
+ */
+@VintfStability
+interface ISupplicantStaIfaceCallback {
+    /**
+     * Used to indicate the result of ANQP (either for IEEE 802.11u Interworking
+     * or Hotspot 2.0) query.
+     *
+     * @param bssid BSSID of the access point.
+     * @param data ANQP data fetched from the access point.
+     *        All the fields in this struct must be empty if the query failed.
+     * @param hs20Data ANQP data fetched from the Hotspot 2.0 access point.
+     *        All the fields in this struct must be empty if the query failed.
+     */
+    oneway void onAnqpQueryDone(in byte[] bssid, in AnqpData data, in Hs20AnqpData hs20Data);
+
+    /**
+     * Used to indicate an association rejection received from the AP
+     * to which the connection is being attempted.
+     *
+     * @param assocRejectData Association Rejection related information.
+     */
+    oneway void onAssociationRejected(in AssociationRejectionData assocRejectData);
+
+    /**
+     * Used to indicate the timeout of authentication to an AP.
+     *
+     * @param bssid BSSID of the corresponding AP.
+     */
+    oneway void onAuthenticationTimeout(in byte[] bssid);
+
+    /**
+     * Indicates BTM request frame handling status.
+     *
+     * @param tmData Data retrieved from received BSS transition management
+     * request frame.
+     */
+    oneway void onBssTmHandlingDone(in BssTmData tmData);
+
+    /**
+     * Used to indicate the change of active bssid.
+     * This is useful to figure out when the driver/firmware roams to a bssid
+     * on its own.
+     *
+     * @param reason Reason why the bssid changed.
+     * @param bssid BSSID of the corresponding AP.
+     */
+    oneway void onBssidChanged(in BssidChangeReason reason, in byte[] bssid);
+
+    /**
+     * Used to indicate the disconnection from the currently connected
+     * network on this iface.
+     *
+     * @param bssid BSSID of the AP from which we disconnected.
+     * @param locallyGenerated If the disconnect was triggered by
+     *        wpa_supplicant.
+     * @param reasonCode 802.11 code to indicate the disconnect reason
+     *        from access point. Refer to section 8.4.1.7 of IEEE802.11 spec.
+     */
+    oneway void onDisconnected(
+            in byte[] bssid, in boolean locallyGenerated, in StaIfaceReasonCode reasonCode);
+
+    /**
+     * Indicates a DPP failure event.
+     *
+     * ssid: A string indicating the SSID for the AP that the Enrollee attempted to connect.
+     * channelList: A string containing a list of operating channels and operating classes
+     *     indicating the channels that the Enrollee scanned in attempting to discover the AP.
+     *     The list conforms to the following ABNF syntax:
+     *         channel-list2 = class-and-channels *(“,” class-and-channels)
+     *         class-and-channels = class “/” channel *(“,” channel)
+     *         class = 1*3DIGIT
+     *         channel = 1*3DIGIT
+     * bandList: A list of band parameters that are supported by the Enrollee expressed as the
+     *     Operating Class.
+     */
+    oneway void onDppFailure(
+            in DppFailureCode code, in String ssid, in String channelList, in char[] bandList);
+
+    /**
+     * Indicates a DPP progress event.
+     */
+    oneway void onDppProgress(in DppProgressCode code);
+
+    /**
+     * Indicates a DPP success event.
+     */
+    oneway void onDppSuccess(in DppEventType event);
+
+    /**
+     * Indicates DPP configuration received success event (Enrolee mode).
+     */
+    oneway void onDppSuccessConfigReceived(
+            in byte[] ssid, in String password, in byte[] psk, in DppAkm securityAkm);
+
+    /**
+     * Indicates DPP configuration sent success event (Configurator mode).
+     */
+    oneway void onDppSuccessConfigSent();
+
+    /**
+     * Indicates an EAP authentication failure.
+     * @param errorCode Error code for EAP authentication failure.
+     *        Either standard error code (enum EapErrorCode) or
+     *        private error code defined by network provider.
+     */
+    oneway void onEapFailure(in int errorCode);
+
+    /**
+     * Used to indicate that the external radio work can start now.
+     *
+     * @param id Identifier generated for the radio work request.
+     */
+    oneway void onExtRadioWorkStart(in int id);
+
+    /**
+     * Used to indicate that the external radio work request has timed out.
+     *
+     * @param id Identifier generated for the radio work request.
+     */
+    oneway void onExtRadioWorkTimeout(in int id);
+
+    /**
+     * Used to indicate a Hotspot 2.0 imminent deauth notice.
+     *
+     * @param bssid BSSID of the access point.
+     * @param reasonCode Code to indicate the deauth reason.
+     *        Refer to section 3.2.1.2 of the Hotspot 2.0 spec.
+     * @param reAuthDelayInSec Delay before reauthenticating.
+     * @param url URL of the server.
+     */
+    oneway void onHs20DeauthImminentNotice(
+            in byte[] bssid, in int reasonCode, in int reAuthDelayInSec, in String url);
+
+    /**
+     * Used to indicate the result of Hotspot 2.0 Icon query.
+     *
+     * @param bssid BSSID of the access point.
+     * @param fileName Name of the file that was requested.
+     * @param data Icon data fetched from the access point.
+     *        Must be empty if the query failed.
+     */
+    oneway void onHs20IconQueryDone(in byte[] bssid, in String fileName, in byte[] data);
+
+    /**
+     * Used to indicate a Hotspot 2.0 subscription remediation event.
+     *
+     * @param bssid BSSID of the access point.
+     * @param osuMethod OSU method.
+     * @param url URL of the server.
+     */
+    oneway void onHs20SubscriptionRemediation(
+            in byte[] bssid, in OsuMethod osuMethod, in String url);
+
+    /**
+     * Used to indicate a Hotspot 2.0 terms and conditions acceptance is requested from the user
+     * before allowing the device to get internet access.
+     *
+     * @param bssid BSSID of the access point.
+     * @param url URL of the T&C server.
+     */
+    oneway void onHs20TermsAndConditionsAcceptanceRequestedNotification(
+            in byte[] bssid, in String url);
+
+    /**
+     * Used to indicate that a new network has been added.
+     *
+     * @param id Network ID allocated to the corresponding network.
+     */
+    oneway void onNetworkAdded(in int id);
+
+    /**
+     * Used to indicate that the supplicant failed to find a network in scan result
+     * which matches with the network capabilities requested by upper layer
+     * for connection.
+     *
+     * @param ssid network name supplicant tried to connect.
+     */
+    oneway void onNetworkNotFound(in byte[] ssid);
+
+    /**
+     * Used to indicate that a network has been removed.
+     *
+     * @param id Network ID allocated to the corresponding network.
+     */
+    oneway void onNetworkRemoved(in int id);
+
+    /**
+     * Indicates pairwise master key (PMK) cache added event.
+     *
+     * @param expirationTimeInSec expiration time in seconds
+     * @param serializedEntry is serialized PMK cache entry, the content is
+     *              opaque for the framework and depends on the native implementation.
+     */
+    oneway void onPmkCacheAdded(in long expirationTimeInSec, in byte[] serializedEntry);
+
+    /**
+     * Used to indicate a state change event on this particular iface. If this
+     * event is triggered by a particular network, the |SupplicantNetworkId|,
+     * |ssid|, |bssid| parameters must indicate the parameters of the network/AP
+     * which caused this state transition.
+     *
+     * @param newState New State of the interface. This must be one of the |State|
+     *        values above.
+     * @param bssid BSSID of the corresponding AP which caused this state
+     *        change event. This must be zero'ed if this event is not
+     *        specific to a particular network.
+     * @param id ID of the corresponding network which caused this
+     *        state change event. This must be invalid (UINT32_MAX) if this
+     *        event is not specific to a particular network.
+     * @param ssid SSID of the corresponding network which caused this state
+     *        change event. This must be empty if this event is not specific
+     *        to a particular network.
+     * @param filsHlpSent If FILS HLP IEs were included in this association.
+     */
+    oneway void onStateChanged(in StaIfaceCallbackState newState, in byte[] bssid, in int id,
+            in byte[] ssid, in boolean filsHlpSent);
+
+    /**
+     * Used to indicate the failure of a WPS connection attempt.
+     *
+     * @param bssid BSSID of the AP to which we initiated WPS
+     *        connection.
+     * @param configError Configuration error code.
+     * @param errorInd Error indication code.
+     */
+    oneway void onWpsEventFail(
+            in byte[] bssid, in WpsConfigError configError, in WpsErrorIndication errorInd);
+
+    /**
+     * Used to indicate the overlap of a WPS PBC connection attempt.
+     */
+    oneway void onWpsEventPbcOverlap();
+
+    /**
+     * Used to indicate the success of a WPS connection attempt.
+     */
+    oneway void onWpsEventSuccess();
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaNetwork.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaNetwork.aidl
new file mode 100644
index 0000000..603e2ad
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaNetwork.aidl
@@ -0,0 +1,1095 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+import android.hardware.wifi.supplicant.AuthAlgMask;
+import android.hardware.wifi.supplicant.EapMethod;
+import android.hardware.wifi.supplicant.EapPhase2Method;
+import android.hardware.wifi.supplicant.GroupCipherMask;
+import android.hardware.wifi.supplicant.GroupMgmtCipherMask;
+import android.hardware.wifi.supplicant.ISupplicantStaNetworkCallback;
+import android.hardware.wifi.supplicant.IfaceType;
+import android.hardware.wifi.supplicant.KeyMgmtMask;
+import android.hardware.wifi.supplicant.NetworkResponseEapSimGsmAuthParams;
+import android.hardware.wifi.supplicant.NetworkResponseEapSimUmtsAuthParams;
+import android.hardware.wifi.supplicant.OcspType;
+import android.hardware.wifi.supplicant.PairwiseCipherMask;
+import android.hardware.wifi.supplicant.ProtoMask;
+import android.hardware.wifi.supplicant.SaeH2eMode;
+
+/**
+ * Interface exposed by the supplicant for each station mode network
+ * configuration it controls.
+ */
+@VintfStability
+interface ISupplicantStaNetwork {
+    /**
+     * Max length of SSID param.
+     */
+    const int SSID_MAX_LEN_IN_BYTES = 32;
+
+    /**
+     * Min length of PSK passphrase param.
+     */
+    const int PSK_PASSPHRASE_MIN_LEN_IN_BYTES = 8;
+
+    /**
+     * Max length of PSK passphrase param.
+     */
+    const int PSK_PASSPHRASE_MAX_LEN_IN_BYTES = 63;
+
+    /**
+     * Max number of WEP keys param.
+     */
+    const int WEP_KEYS_MAX_NUM = 4;
+
+    /**
+     * Length of each WEP40 keys param.
+     */
+    const int WEP40_KEY_LEN_IN_BYTES = 5;
+
+    /**
+     * Length of each WEP104 keys param.
+     */
+    const int WEP104_KEY_LEN_IN_BYTES = 13;
+
+    /**
+     * Disable the network for connection purposes.
+     *
+     * This must trigger a disconnection from the network, if currently
+     * connected to this one.
+     *
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void disable();
+
+    /**
+     * Enable the network for connection purposes.
+     *
+     * This must trigger a connection to the network if:
+     * a) |noConnect| is false, and
+     * b) This is the only network configured, and
+     * c) Is visible in the current scan results.
+     *
+     * @param noConnect Only enable the network, don't trigger a connect.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void enable(in boolean noConnect);
+
+    /**
+     * Set whether to enable SAE PK (Public Key) only mode to enable public AP validation.
+     * When enabled, only SAE PK network is allowed; otherwise PK is optional.
+     * If this API is not called before connecting to an SAE
+     * network, SAE PK mode depends on SAE PK config in wpa_supplicant configuration.
+     * If SAE PK config of wpa_supplicant configuration is not set,
+     * the default mode is optional (support for both PK and standard mode).
+     *
+     * @param enable true to set, false otherwise.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNSUPPORTED|
+     */
+    void enableSaePkOnlyMode(in boolean enable);
+
+    /**
+     * Set EAP OpenSSL Suite-B-192 ciphers for WPA3-Enterprise
+     *        Supported option:
+     *
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void enableSuiteBEapOpenSslCiphers();
+
+    /**
+     * Enable TLS Suite-B in EAP Phase1
+     *
+     * @param enable Set to true to enable TLS Suite-B in EAP phase1
+     *
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void enableTlsSuiteBEapPhase1Param(in boolean enable);
+
+    /**
+     * Get the auth alg mask set for the network.
+     *
+     * @return Combination of |AuthAlgMask| values.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    AuthAlgMask getAuthAlg();
+
+    /**
+     * Get the BSSID set for this network.
+     *
+     * @return bssid Value set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    byte[] getBssid();
+
+    /**
+     * Get EAP Alt subject match set for this network.
+     *
+     * @return value set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    String getEapAltSubjectMatch();
+
+    /**
+     * Get EAP Anonymous Identity set for this network.
+     *
+     * @return identity value set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    byte[] getEapAnonymousIdentity();
+
+    /**
+     * Get EAP CA certificate file path set for this network.
+     *
+     * @return value set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    String getEapCACert();
+
+    /**
+     * Get EAP CA certificate directory path set for this network.
+     *
+     * @return value set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    String getEapCAPath();
+
+    /**
+     * Get EAP Client certificate file path set for this network.
+     *
+     * @return value set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    String getEapClientCert();
+
+    /**
+     * Get EAP Domain suffix match set for this network.
+     *
+     * @return value set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    String getEapDomainSuffixMatch();
+
+    /**
+     * Get whether EAP Open SSL Engine is enabled for this network.
+     *
+     * @return true if set, false otherwise.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    boolean getEapEngine();
+
+    /**
+     * Get EAP Open SSL Engine ID set for this network.
+     *
+     * @return value set.
+     * throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    String getEapEngineId();
+
+    /**
+     * Get EAP Identity set for this network.
+     *
+     * @return value set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    byte[] getEapIdentity();
+
+    /**
+     * Get EAP Method set for this network.
+     *
+     * @return value set.
+     *        Must be one of |EapMethod| values.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    EapMethod getEapMethod();
+
+    /**
+     * Get EAP Password set for this network.
+     *
+     * @return value set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    byte[] getEapPassword();
+
+    /**
+     * Get EAP Phase2 Method set for this network.
+     *
+     * @return value set.
+     *        Must be one of |EapPhase2Method| values.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    EapPhase2Method getEapPhase2Method();
+
+    /**
+     * Get EAP private key Id set for this network.
+     *
+     * @return value set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|)
+     */
+    String getEapPrivateKeyId();
+
+    /**
+     * Get EAP subject match set for this network.
+     *
+     * @return value set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    String getEapSubjectMatch();
+
+    /**
+     * Get whether enhanced directional multi-gigabit (802.11ay EDMG) is enabled for this network.
+     *
+     * @return true if set, false otherwise.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    boolean getEdmg();
+
+    /**
+     * Get the group cipher mask set for the network.
+     *
+     * @return Combination of |GroupCipherMask| values.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     */
+    GroupCipherMask getGroupCipher();
+
+    /**
+     * Get the group management cipher mask set for the network.
+     *
+     * @return Combination of |GroupMgmtCipherMask| values.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    GroupMgmtCipherMask getGroupMgmtCipher();
+
+    /**
+     * Retrieves the ID allocated to this network by the supplicant.
+     *
+     * This is not the |SSID| of the network, but an internal identifier for
+     * this network used by the supplicant.
+     *
+     * @return Network ID.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    int getId();
+
+    /**
+     * Get ID string set for this network.
+     * Network identifier string for external scripts.
+     *
+     * @return ID string set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    String getIdStr();
+
+    /**
+     * Retrieves the name of the interface this network belongs to.
+     *
+     * @return Name of the network interface, e.g., wlan0
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    String getInterfaceName();
+
+    /**
+     * Get the key mgmt mask set for the network.
+     *
+     * @return Combination of |KeyMgmtMask| values.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     */
+    KeyMgmtMask getKeyMgmt();
+
+    /**
+     * Get OCSP (Online Certificate Status Protocol) type for this network.
+     *
+     * @return ocsp type.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    OcspType getOcsp();
+
+    /**
+     * Get the pairwise cipher mask set for the network.
+     *
+     * @return Combination of |PairwiseCipherMask| values.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     */
+    PairwiseCipherMask getPairwiseCipher();
+
+    /**
+     * Get the proto mask set for the network.
+     *
+     * @return Combination of |ProtoMask| values.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     */
+    ProtoMask getProto();
+
+    /**
+     * Get raw psk for WPA_PSK network.
+     *
+     * @return value set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    byte[] getPsk();
+
+    /**
+     * Get passphrase for WPA_PSK network.
+     * Must return a failure if network has no passphrase set (use |getPsk| if
+     * network was configured with raw psk instead).
+     *
+     * @return value set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    String getPskPassphrase();
+
+    /**
+     * Get whether RequirePmf is enabled for this network.
+     *
+     * @return true if set, false otherwise.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    boolean getRequirePmf();
+
+    /**
+     * Get SAE password for WPA3-Personal
+     *
+     * @return value set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    String getSaePassword();
+
+    /**
+     * Get SAE password ID for WPA3-Personal
+     *
+     * @return value set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    String getSaePasswordId();
+
+    /**
+     * Get whether Probe Requests are being sent for this network (hidden).
+     *
+     * @return true if set, false otherwise.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    boolean getScanSsid();
+
+    /**
+     *
+     * Getters for the various network params.
+     *
+     */
+
+    /**
+     * Get SSID for this network.
+     *
+     * @return value set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    byte[] getSsid();
+
+    /**
+     * Retrieves the type of the interface this network belongs to.
+     *
+     * @return Type of the network interface, e.g., STA.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    IfaceType getType();
+
+    /**
+     * Get WAPI certificate suite name set for this network.
+     *
+     * @return The name of a suite.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     */
+    String getWapiCertSuite();
+
+    /**
+     * Get WEP key for WEP network.
+     *
+     * @param keyIdx Index of wep key to be fetched.
+     *        Max of |WEP_KEYS_MAX_NUM|.
+     * @return value set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    byte[] getWepKey(in int keyIdx);
+
+    /**
+     * Get default Tx key index for WEP network.
+     *
+     * @return value set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    int getWepTxKeyIdx();
+
+    /**
+     * Retrieves a WPS-NFC configuration token for this network.
+     *
+     * @return Bytes representing WPS-NFC configuration token.
+     *         This is a dump of all the WPS atrributes of the AP configuration
+     *         as specified in the Wi-Fi Protected Setup Specification.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    byte[] getWpsNfcConfigurationToken();
+
+    /**
+     * Register for callbacks from this network.
+     *
+     * These callbacks are invoked for events that are specific to this network.
+     * Registration of multiple callback objects is supported. These objects must
+     * be automatically deleted when the corresponding client process is dead or
+     * if this network is removed.
+     *
+     * @param callback An instance of the |ISupplicantStaNetworkCallback| AIDL
+     *        interface object.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void registerCallback(in ISupplicantStaNetworkCallback callback);
+
+    /**
+     * Initiate connection to this network.
+     *
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void select();
+
+    /**
+     * Used to send a response to the
+     * |ISupplicantNetworkCallback.onNetworkEapIdentityRequest| request.
+     *
+     * @param identity Identity string containing the IMSI.
+     * @param encryptedIdentity Identity string containing the encrypted IMSI.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void sendNetworkEapIdentityResponse(in byte[] identity, in byte[] encryptedIdentity);
+
+    /**
+     * Used to send a response to the
+     * |ISupplicantNetworkCallback.onNetworkEapSimGsmAuthRequest| request.
+     *
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void sendNetworkEapSimGsmAuthFailure();
+
+    /**
+     * Used to send a response to the
+     * |ISupplicantNetworkCallback.onNetworkEapSimGsmAuthRequest| request.
+     *
+     * @param params Params to be used for EAP GSM authentication.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void sendNetworkEapSimGsmAuthResponse(in NetworkResponseEapSimGsmAuthParams[] params);
+
+    /**
+     * Used to send a response to the
+     * |ISupplicantNetworkCallback.onNetworkEapSimUmtsAuthRequest| request.
+     *
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void sendNetworkEapSimUmtsAuthFailure();
+
+    /**
+     * Used to send a response to the
+     * |ISupplicantNetworkCallback.onNetworkEapSimUmtsAuthRequest| request.
+     *
+     * @param params Params to be used for EAP UMTS authentication.
+     * @throws ServiceSpecificException with one of the following values:
+
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void sendNetworkEapSimUmtsAuthResponse(in NetworkResponseEapSimUmtsAuthParams params);
+
+    /**
+     * Used to send a response to the
+     * |ISupplicantNetworkCallback.onNetworkEapSimUmtsAuthRequest| request.
+     *
+     * @param auts Params to be used for EAP UMTS authentication.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void sendNetworkEapSimUmtsAutsResponse(in byte[] auts);
+
+    /**
+     * Set auth alg mask for the network.
+     *
+     * @param authAlgMask value to set.
+     *        Combination of |ProtoMask| values.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setAuthAlg(in AuthAlgMask authAlgMask);
+
+    /**
+     * Set the network to only connect to an AP with provided BSSID.
+     *
+     * @param bssid value to set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setBssid(in byte[] bssid);
+
+    /**
+     * Set EAP Alt subject match for this network.
+     *
+     * @param match value to set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setEapAltSubjectMatch(in String match);
+
+    /**
+     * Set EAP Anonymous Identity for this network.
+     *
+     * @param identity value to set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setEapAnonymousIdentity(in byte[] identity);
+
+    /**
+     * Set EAP CA certificate file path for this network.
+     *
+     * @param path value to set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setEapCACert(in String path);
+
+    /**
+     * Set EAP CA certificate directory path for this network.
+     *
+     * @param path value to set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setEapCAPath(in String path);
+
+    /**
+     * Set EAP Client certificate file path for this network.
+     *
+     * @param path value to set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setEapClientCert(in String path);
+
+    /**
+     * Set EAP Domain suffix match for this network.
+     *
+     * @param match value to set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setEapDomainSuffixMatch(in String match);
+
+    /**
+     * Set EAP encrypted IMSI Identity for this network.
+     *
+     * @param identity Identity string built from the encrypted IMSI.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setEapEncryptedImsiIdentity(in byte[] identity);
+
+    /**
+     * Enable EAP Open SSL Engine for this network.
+     *
+     * @param enable true to set, false otherwise.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setEapEngine(in boolean enable);
+
+    /**
+     * Set EAP Open SSL Engine ID for this network.
+     *
+     * @param id value to set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setEapEngineID(in String id);
+
+    /**
+     * Enable Extensible Authentication (EAP) - Re-authentication Protocol (ERP) for this network.
+     *
+     * @param enable true to set, false otherwise.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setEapErp(in boolean enable);
+
+    /**
+     * Set EAP Identity for this network.
+     *
+     * @param identity value to set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setEapIdentity(in byte[] identity);
+
+    /**
+     * Set EAP Method for this network.
+     *
+     * @param method value to be set.
+     *        Must be one of |EapMethod| values.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setEapMethod(in EapMethod method);
+
+    /**
+     * Set EAP Password for this network.
+     *
+     * @param password value to set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setEapPassword(in byte[] password);
+
+    /**
+     * Set EAP Phase2 Method for this network.
+     *
+     * EAP method needs to be set for this to work.
+     *
+     * @param method value to set.
+     *        Must be one of |EapPhase2Method| values.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setEapPhase2Method(in EapPhase2Method method);
+
+    /**
+     * Set EAP private key Id for this network.
+     * This is used if private key operations for EAP-TLS are performed
+     * using a smartcard.
+     *
+     * @param id value to set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setEapPrivateKeyId(in String id);
+
+    /**
+     * Set EAP subject match for this network.
+     *
+     * @param match value to set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setEapSubjectMatch(in String match);
+
+    /**
+     * Set whether to enable enhanced directional multi-gigabit (802.11ay EDMG).
+     * Only allowed if hw mode is |HOSTAPD_MODE_IEEE80211AD|
+     *
+     * @param enable true to set, false otherwise.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setEdmg(in boolean enable);
+
+    /**
+     * Set group cipher mask for the network.
+     *
+     * @param groupCipherMask value to set.
+     *        Combination of |ProtoMask| values.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     */
+    void setGroupCipher(in GroupCipherMask groupCipherMask);
+
+    /**
+     * Set group management cipher mask for the network.
+     *
+     * @param groupMgmtCipherMask value to set.
+     *        Combination of |GroupMgmtCipherMask| values.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setGroupMgmtCipher(in GroupMgmtCipherMask groupMgmtCipherMask);
+
+    /**
+     * Set ID string for this network.
+     * Network identifier string for external scripts.
+     *
+     * @param idStr ID string value to set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setIdStr(in String idStr);
+
+    /**
+     * Set key management mask for the network.
+     *
+     * @param keyMgmtMask value to set.
+     *        Combination of |KeyMgmtMask| values.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     */
+    void setKeyMgmt(in KeyMgmtMask keyMgmtMask);
+
+    /**
+     * Set OCSP (Online Certificate Status Protocol) type for this network.
+     *
+     * @param ocspType value to set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setOcsp(in OcspType ocspType);
+
+    /**
+     * Set pairwise cipher mask for the network.
+     *
+     * @param pairwiseCipherMask value to set.
+     *        Combination of |ProtoMask| values.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     */
+    void setPairwiseCipher(in PairwiseCipherMask pairwiseCipherMask);
+
+    /**
+     * Add a pairwise master key (PMK) into supplicant PMK cache.
+     *
+     * @param serializedEntry is serialized PMK cache entry, the content is
+     *              opaque for the framework and depends on the native implementation.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setPmkCache(in byte[] serializedEntry);
+
+    /**
+     * This field can be used to enable proactive key caching which is also
+     * known as opportunistic PMKSA caching for WPA2. This is disabled (0)
+     * by default unless default value is changed with the global okc=1
+     * parameter.
+     *
+     * Proactive key caching is used to make supplicant assume that the APs
+     * are using the same PMK and generate PMKSA cache entries without
+     * doing RSN pre-authentication. This requires support from the AP side
+     * and is normally used with wireless switches that co-locate the
+     * authenticator.
+     *
+     * @param enable true to set, false otherwise.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setProactiveKeyCaching(in boolean enable);
+
+    /**
+     * Set proto mask for the network.
+     *
+     * @param protoMask value to set.
+     *        Combination of |ProtoMask| values.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     */
+    void setProto(in ProtoMask protoMask);
+
+    /**
+     * Set raw psk for WPA_PSK network.
+     *
+     * @param psk value to set as specified in IEEE 802.11i-2004 standard.
+     *        This is the calculated using 'wpa_passphrase <ssid> [passphrase]'
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setPsk(in byte[] psk);
+
+    /**
+     * Set passphrase for WPA_PSK network.
+     *
+     * @param psk value to set.
+     *        Length of value must be between
+     *        |PSK_PASSPHRASE_MIN_LEN_IN_BYTES| and
+     *        |PSK_PASSPHRASE_MAX_LEN_IN_BYTES|.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setPskPassphrase(in String psk);
+
+    /**
+     * Set whether RequirePmf is enabled for this network.
+     *
+     * @param enable true to set, false otherwise.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setRequirePmf(in boolean enable);
+
+    /**
+     * Set SAE H2E (Hash-to-Element) mode.
+     *
+     * @param mode SAE H2E supporting mode.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setSaeH2eMode(in SaeH2eMode mode);
+
+    /**
+     * Set SAE password for WPA3-Personal
+     *
+     * @param saePassword string with the above option
+     *
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setSaePassword(in String saePassword);
+
+    /**
+     * Set SAE password ID for WPA3-Personal
+     *
+     * @param sae_password_id string with the above option
+     *
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setSaePasswordId(in String saePasswordId);
+
+    /**
+     * Set whether to send probe requests for this network (hidden).
+     *
+     * @param enable true to set, false otherwise.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setScanSsid(in boolean enable);
+
+    /**
+     *
+     * Setters for the various network params.
+     * These correspond to elements of |wpa_sssid| struct used internally by
+     * the supplicant to represent each network.
+     *
+     */
+
+    /**
+     * Set SSID for this network.
+     *
+     * @param ssid value to set.
+     *        Max length of |SSID_MAX_LEN_IN_BYTES|.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setSsid(in byte[] ssid);
+
+    /**
+     * Set PPS MO ID for this network.
+     * (Hotspot 2.0 PerProviderSubscription/UpdateIdentifier)
+     *
+     * @param id ID value to set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setUpdateIdentifier(in int id);
+
+    /**
+     * Set WAPI certificate suite name for this network.
+     *
+     * @param suite value to set.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     */
+    void setWapiCertSuite(in String suite);
+
+    /**
+     * Set WEP key for WEP network.
+     *
+     * @param keyIdx Index of wep key to set.
+     *        Max of |WEP_KEYS_MAX_NUM|.
+     * @param wepKey value to set.
+     *        Length of each key must be either
+     *        |WEP40_KEY_LEN_IN_BYTES| or
+     *        |WEP104_KEY_LEN_IN_BYTES|.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setWepKey(in int keyIdx, in byte[] wepKey);
+
+    /**
+     * Set default Tx key index for WEP network.
+     *
+     * @param keyIdx Value to set.
+     *        Max of |WEP_KEYS_MAX_NUM|.
+     * @throws ServiceSpecificException with one of the following values:
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    void setWepTxKeyIdx(in int keyIdx);
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaNetworkCallback.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaNetworkCallback.aidl
new file mode 100644
index 0000000..c28b494
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaNetworkCallback.aidl
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+import android.hardware.wifi.supplicant.NetworkRequestEapSimGsmAuthParams;
+import android.hardware.wifi.supplicant.NetworkRequestEapSimUmtsAuthParams;
+import android.hardware.wifi.supplicant.TransitionDisableIndication;
+
+/**
+ * Callback Interface exposed by the supplicant service
+ * for each network (ISupplicantStaNetwork).
+ *
+ * Clients need to host an instance of this AIDL interface object and
+ * pass a reference of the object to the supplicant via the
+ * corresponding |ISupplicantStaNetwork.registerCallback| method.
+ */
+@VintfStability
+interface ISupplicantStaNetworkCallback {
+    /**
+     * Used to request EAP Identity for this particular network.
+     *
+     * The response for the request must be sent using the corresponding
+     * |ISupplicantNetwork.sendNetworkEapIdentityResponse| call.
+     */
+    oneway void onNetworkEapIdentityRequest();
+
+    /**
+     * Used to request EAP GSM SIM authentication for this particular network.
+     *
+     * The response for the request must be sent using the corresponding
+     * |ISupplicantNetwork.sendNetworkEapSimGsmAuthResponse| call.
+     *
+     * @param params Params associated with the request.
+     */
+    oneway void onNetworkEapSimGsmAuthRequest(in NetworkRequestEapSimGsmAuthParams params);
+
+    /**
+     * Used to request EAP UMTS SIM authentication for this particular network.
+     *
+     * The response for the request must be sent using the corresponding
+     * |ISupplicantNetwork.sendNetworkEapSimUmtsAuthResponse| call.
+     *
+     * @param params Params associated with the request.
+     */
+    oneway void onNetworkEapSimUmtsAuthRequest(in NetworkRequestEapSimUmtsAuthParams params);
+
+    /**
+     * Used to notify WPA3 transition disable.
+     */
+    oneway void onTransitionDisable(in TransitionDisableIndication ind);
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/IfaceInfo.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/IfaceInfo.aidl
new file mode 100644
index 0000000..7792142
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/IfaceInfo.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+import android.hardware.wifi.supplicant.IfaceType;
+
+/**
+ * Structure describing the type and name of an iface
+ * controlled by the supplicant.
+ */
+@VintfStability
+parcelable IfaceInfo {
+    /**
+     * Type of the network interface.
+     */
+    IfaceType type;
+    /**
+     * Name of the network interface, e.g., wlan0
+     */
+    String name;
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/IfaceType.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/IfaceType.aidl
new file mode 100644
index 0000000..e39dcd1
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/IfaceType.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * List of Iface types supported.
+ */
+@VintfStability
+@Backing(type="int")
+enum IfaceType {
+    STA,
+    P2P,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/KeyMgmtMask.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/KeyMgmtMask.aidl
new file mode 100644
index 0000000..f0c3345
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/KeyMgmtMask.aidl
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * Possible mask of values for KeyMgmt param.
+ * See /external/wpa_supplicant_8/src/common/defs.h for
+ * the historical values (starting at WPA_KEY_MGMT_IEEE8021X).
+ */
+@VintfStability
+@Backing(type="int")
+enum KeyMgmtMask {
+    WPA_EAP = 1 << 0,
+    WPA_PSK = 1 << 1,
+    NONE = 1 << 2,
+    IEEE8021X = 1 << 3,
+    FT_EAP = 1 << 5,
+    FT_PSK = 1 << 6,
+    OSEN = 1 << 15,
+    /**
+     * WPA using EAP authentication with stronger SHA256-based algorithms
+     */
+    WPA_EAP_SHA256 = 1 << 7,
+    /**
+     * WPA pre-shared key with stronger SHA256-based algorithms
+     */
+    WPA_PSK_SHA256 = 1 << 8,
+    /**
+     * WPA3-Personal SAE Key management
+     */
+    SAE = 1 << 10,
+    /**
+     * WPA3-Enterprise Suite-B Key management
+     */
+    SUITE_B_192 = 1 << 17,
+    /**
+     * Enhacned Open (OWE) Key management
+     */
+    OWE = 1 << 22,
+    /**
+     * Easy Connect (DPP) Key management
+     */
+    DPP = 1 << 23,
+    /*
+     * WAPI Psk
+     */
+    WAPI_PSK = 1 << 12,
+    /**
+     * WAPI Cert
+     */
+    WAPI_CERT = 1 << 13,
+    /**
+     * FILS shared key authentication with sha-256
+     */
+    FILS_SHA256 = 1 << 18,
+    /**
+     * FILS shared key authentication with sha-384
+     */
+    FILS_SHA384 = 1 << 19,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/LegacyMode.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/LegacyMode.aidl
new file mode 100644
index 0000000..f933f6c
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/LegacyMode.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * Detailed network mode for legacy network
+ */
+@VintfStability
+@Backing(type="int")
+enum LegacyMode {
+    UNKNOWN = 0,
+    /**
+     * For 802.11a
+     */
+    A_MODE = 1,
+    /**
+     * For 802.11b
+     */
+    B_MODE = 2,
+    /**
+     * For 802.11g
+     */
+    G_MODE = 3,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/MacAddress.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/MacAddress.aidl
new file mode 100644
index 0000000..40ad22a
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/MacAddress.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * Byte array representing a Mac Address. Use when we need
+ * to pass an array of Mac Addresses to a method, as 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/supplicant/aidl/android/hardware/wifi/supplicant/MboAssocDisallowedReasonCode.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/MboAssocDisallowedReasonCode.aidl
new file mode 100644
index 0000000..41868aa
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/MboAssocDisallowedReasonCode.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ *  MBO spec v1.2, 4.2.4 Table 14: MBO Association disallowed reason code attribute
+ *  values.
+ */
+@VintfStability
+@Backing(type="byte")
+enum MboAssocDisallowedReasonCode {
+    RESERVED = 0,
+    UNSPECIFIED = 1,
+    MAX_NUM_STA_ASSOCIATED = 2,
+    AIR_INTERFACE_OVERLOADED = 3,
+    AUTH_SERVER_OVERLOADED = 4,
+    INSUFFICIENT_RSSI = 5,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/MboCellularDataConnectionPrefValue.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/MboCellularDataConnectionPrefValue.aidl
new file mode 100644
index 0000000..98f707e
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/MboCellularDataConnectionPrefValue.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ *  MBO spec v1.2, 4.2.5 Table 16: MBO Cellular Data connection preference
+ *  attribute values. AP use this to indicate STA, its preference for the
+ *  STA to move from BSS to cellular network.
+ */
+@VintfStability
+@Backing(type="int")
+enum MboCellularDataConnectionPrefValue {
+    EXCLUDED = 0,
+    NOT_PREFERRED = 1,
+    /*
+     * 2-254 Reserved.
+     */
+    PREFERRED = 255,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/MboTransitionReasonCode.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/MboTransitionReasonCode.aidl
new file mode 100644
index 0000000..66ad9ee
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/MboTransitionReasonCode.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ *  MBO spec v1.2, 4.2.6 Table 18: MBO transition reason code attribute
+ *  values.
+ */
+@VintfStability
+@Backing(type="byte")
+enum MboTransitionReasonCode {
+    UNSPECIFIED = 0,
+    EXCESSIVE_FRAME_LOSS = 1,
+    EXCESSIVE_TRAFFIC_DELAY = 2,
+    INSUFFICIENT_BANDWIDTH = 3,
+    LOAD_BALANCING = 4,
+    LOW_RSSI = 5,
+    RX_EXCESSIVE_RETRIES = 6,
+    HIGH_INTERFERENCE = 7,
+    GRAY_ZONE = 8,
+    TRANSITION_TO_PREMIUM_AP = 9,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/MiracastMode.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/MiracastMode.aidl
new file mode 100644
index 0000000..4eaaf1d
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/MiracastMode.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * Enum describing the modes of Miracast supported
+ * via driver commands.
+ */
+@VintfStability
+@Backing(type="byte")
+enum MiracastMode {
+    DISABLED = 0,
+    /**
+     * Operating as source.
+     */
+    SOURCE = 1,
+    /**
+     * Operating as sink.
+     */
+    SINK = 2,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/NetworkRequestEapSimGsmAuthParams.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/NetworkRequestEapSimGsmAuthParams.aidl
new file mode 100644
index 0000000..c706c81
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/NetworkRequestEapSimGsmAuthParams.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+import android.hardware.wifi.supplicant.GsmRand;
+
+/**
+ * Params of |onNetworkEapSimGsmAuthRequest| request. (Refer RFC 4186)
+ */
+@VintfStability
+parcelable NetworkRequestEapSimGsmAuthParams {
+    GsmRand[] rands;
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/NetworkRequestEapSimUmtsAuthParams.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/NetworkRequestEapSimUmtsAuthParams.aidl
new file mode 100644
index 0000000..2f5e7fa
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/NetworkRequestEapSimUmtsAuthParams.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * Params of |onNetworkEapSimUmtsAuthRequest| request. (Refer RFC 4187)
+ */
+@VintfStability
+parcelable NetworkRequestEapSimUmtsAuthParams {
+    byte[/* 16 */] rand;
+    byte[/* 16 */] autn;
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/NetworkResponseEapSimGsmAuthParams.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/NetworkResponseEapSimGsmAuthParams.aidl
new file mode 100644
index 0000000..38929a2
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/NetworkResponseEapSimGsmAuthParams.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * Params of |sendNetworkEapSimGsmAuthResponse| request. (Refer RFC 4186)
+ */
+@VintfStability
+parcelable NetworkResponseEapSimGsmAuthParams {
+    byte[/* 8 */] kc;
+    byte[/* 4 */] sres;
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/NetworkResponseEapSimUmtsAuthParams.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/NetworkResponseEapSimUmtsAuthParams.aidl
new file mode 100644
index 0000000..5311016
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/NetworkResponseEapSimUmtsAuthParams.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * Params of |sendNetworkEapSimUmtsAuthResponse| request. (Refer RFC 4187)
+ */
+@VintfStability
+parcelable NetworkResponseEapSimUmtsAuthParams {
+    byte[] res;
+    byte[/* 16 */] ik;
+    byte[/* 16 */] ck;
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/OceRssiBasedAssocRejectAttr.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/OceRssiBasedAssocRejectAttr.aidl
new file mode 100644
index 0000000..09ec09c
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/OceRssiBasedAssocRejectAttr.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * OceRssiBasedAssocRejectAttr is extracted from (Re-)Association response
+ * frame from an OCE AP to indicate that the AP has rejected the
+ * (Re-)Association request on the basis of insufficient RSSI.
+ * Refer OCE spec v1.0 section 4.2.2 Table 7.
+ */
+@VintfStability
+parcelable OceRssiBasedAssocRejectAttr {
+    /*
+     * Delta RSSI - The difference in dB between the minimum RSSI at which
+     * the AP would accept a (Re-)Association request from the STA before
+     * Retry Delay expires and the AP's measurement of the RSSI at which the
+     * (Re-)Association request was received.
+     */
+    int deltaRssi;
+    /*
+     * Retry Delay - The time period in seconds for which the AP will not
+     * accept any subsequent (Re-)Association requests from the STA, unless
+     * the received RSSI has improved by Delta RSSI.
+     */
+    int retryDelayS;
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/OcspType.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/OcspType.aidl
new file mode 100644
index 0000000..876fb11
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/OcspType.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * OcspType: The type of OCSP request.
+ */
+@VintfStability
+@Backing(type="int")
+enum OcspType {
+    NONE,
+    REQUEST_CERT_STATUS,
+    REQUIRE_CERT_STATUS,
+    REQUIRE_ALL_CERTS_STATUS,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/OsuMethod.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/OsuMethod.aidl
new file mode 100644
index 0000000..a060365
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/OsuMethod.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * OSU Method. Refer to section 4.8.1.3 of the Hotspot 2.0 spec.
+ */
+@VintfStability
+@Backing(type="byte")
+enum OsuMethod {
+    OMA_DM = 0,
+    SOAP_XML_SPP = 1,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pGroupCapabilityMask.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pGroupCapabilityMask.aidl
new file mode 100644
index 0000000..bda3c34
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pGroupCapabilityMask.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * P2P group capability.
+ * See /external/wpa_supplicant_8/src/common/ieee802_11_defs.h
+ * for all possible values (starting at P2P_GROUP_CAPAB_GROUP_OWNER).
+ */
+@VintfStability
+@Backing(type="int")
+enum P2pGroupCapabilityMask {
+    GROUP_OWNER = 1 << 0,
+    PERSISTENT_GROUP = 1 << 1,
+    GROUP_LIMIT = 1 << 2,
+    INTRA_BSS_DIST = 1 << 3,
+    CROSS_CONN = 1 << 4,
+    PERSISTENT_RECONN = 1 << 5,
+    GROUP_FORMATION = 1 << 6,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pProvDiscStatusCode.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pProvDiscStatusCode.aidl
new file mode 100644
index 0000000..9effd0a
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pProvDiscStatusCode.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * Status codes for P2P discovery.
+ */
+@VintfStability
+@Backing(type="byte")
+enum P2pProvDiscStatusCode {
+    SUCCESS = 0,
+    TIMEOUT = 1,
+    REJECTED = 2,
+    TIMEOUT_JOIN = 3,
+    INFO_UNAVAILABLE = 4,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pStatusCode.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pStatusCode.aidl
new file mode 100644
index 0000000..4020f9e
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pStatusCode.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * Status codes for P2P operations.
+ */
+@VintfStability
+@Backing(type="int")
+enum P2pStatusCode {
+    SUCCESS = 0,
+    FAIL_INFO_CURRENTLY_UNAVAILABLE = 1,
+    FAIL_INCOMPATIBLE_PARAMS = 2,
+    FAIL_LIMIT_REACHED = 3,
+    FAIL_INVALID_PARAMS = 4,
+    FAIL_UNABLE_TO_ACCOMMODATE = 5,
+    FAIL_PREV_PROTOCOL_ERROR = 6,
+    FAIL_NO_COMMON_CHANNELS = 7,
+    FAIL_UNKNOWN_GROUP = 8,
+    FAIL_BOTH_GO_INTENT_15 = 9,
+    FAIL_INCOMPATIBLE_PROV_METHOD = 10,
+    FAIL_REJECTED_BY_USER = 11,
+    SUCCESS_DEFERRED = 12,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/PairwiseCipherMask.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/PairwiseCipherMask.aidl
new file mode 100644
index 0000000..7179fea
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/PairwiseCipherMask.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * Possible mask of values for PairwiseCipher param.
+ * See /external/wpa_supplicant_8/src/common/defs.h for
+ * the historical values (starting at WPA_CIPHER_NONE).
+ */
+@VintfStability
+@Backing(type="int")
+enum PairwiseCipherMask {
+    NONE = 1 << 0,
+    TKIP = 1 << 3,
+    CCMP = 1 << 4,
+    /**
+     * GCMP-128 Pairwise Cipher
+     */
+    GCMP_128 = 1 << 6,
+    /**
+     * SMS4 Pairwise Cipher
+     */
+    SMS4 = 1 << 7,
+    /**
+     * GCMP-256 Pairwise Cipher
+     */
+    GCMP_256 = 1 << 8,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ProtoMask.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ProtoMask.aidl
new file mode 100644
index 0000000..dc3d80b
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ProtoMask.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * Possible mask of values for Proto param.
+ * See /external/wpa_supplicant_8/src/common/defs.h for
+ * the historical values (starting at WPA_PROTO_WPA).
+ */
+@VintfStability
+@Backing(type="int")
+enum ProtoMask {
+    WPA = 1 << 0,
+    RSN = 1 << 1,
+    WAPI = 1 << 2,
+    OSEN = 1 << 3,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/RxFilterType.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/RxFilterType.aidl
new file mode 100644
index 0000000..5dfb73e
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/RxFilterType.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * Enum describing the types of RX filter supported
+ * via driver commands.
+ */
+@VintfStability
+@Backing(type="byte")
+enum RxFilterType {
+    V4_MULTICAST = 0,
+    V6_MULTICAST = 1,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/SaeH2eMode.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/SaeH2eMode.aidl
new file mode 100644
index 0000000..48a879b
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/SaeH2eMode.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * SAE Hash-to-Element mode.
+ */
+@VintfStability
+@Backing(type="byte")
+enum SaeH2eMode {
+    /**
+     * Hash-to-Element is disabled, only Hunting & Pecking is allowed.
+     */
+    DISABLED,
+    /**
+     * Both Hash-to-Element and Hunting & Pecking are allowed.
+     */
+    H2E_OPTIONAL,
+    /**
+     * Only Hash-to-Element is allowed.
+     */
+    H2E_MANDATORY,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/StaIfaceCallbackState.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/StaIfaceCallbackState.aidl
new file mode 100644
index 0000000..19f6f88
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/StaIfaceCallbackState.aidl
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * Various states of the interface reported by |onStateChanged|.
+ */
+@VintfStability
+@Backing(type="int")
+enum StaIfaceCallbackState {
+    /**
+     * This state indicates that client is not associated, but is likely to
+     * start looking for an access point. This state is entered when a
+     * connection is lost.
+     */
+    DISCONNECTED = 0,
+    /**
+     * This state is entered if the network interface is disabled, e.g.,
+     * due to rfkill. the supplicant refuses any new operations that would
+     * use the radio until the interface has been enabled.
+     */
+    IFACE_DISABLED = 1,
+    /**
+     * This state is entered if there are no enabled networks in the
+     * configuration. the supplicant is not trying to associate with a new
+     * network and external interaction (e.g., ctrl_iface call to add or
+     * enable a network) is needed to start association.
+     */
+    INACTIVE = 2,
+    /**
+     * This state is entered when the supplicant starts scanning for a
+     * network.
+     */
+    SCANNING = 3,
+    /**
+     * This state is entered when the supplicant has found a suitable BSS
+     * to authenticate with and the driver is configured to try to
+     * authenticate with this BSS. This state is used only with drivers
+     * that use the supplicant as the SME.
+     */
+    AUTHENTICATING = 4,
+    /**
+     * This state is entered when the supplicant has found a suitable BSS
+     * to associate with and the driver is configured to try to associate
+     * with this BSS in ap_scan=1 mode. When using ap_scan=2 mode, this
+     * state is entered when the driver is configured to try to associate
+     * with a network using the configured SSID and security policy.
+     */
+    ASSOCIATING = 5,
+    /**
+     * This state is entered when the driver reports that association has
+     * been successfully completed with an AP. If IEEE 802.1X is used
+     * (with or without WPA/WPA2), the supplicant remains in this state
+     * until the IEEE 802.1X/EAPOL authentication has been completed.
+     */
+    ASSOCIATED = 6,
+    /**
+     * This state is entered when WPA/WPA2 4-Way Handshake is started. In
+     * case of WPA-PSK, this happens when receiving the first EAPOL-Key
+     * frame after association. In case of WPA-EAP, this state is entered
+     * when the IEEE 802.1X/EAPOL authentication has been completed.
+     */
+    FOURWAY_HANDSHAKE = 7,
+    /**
+     * This state is entered when 4-Way Key Handshake has been completed
+     * (i.e., when the supplicant sends out message 4/4) and when Group
+     * Key rekeying is started by the AP (i.e., when supplicant receives
+     * message 1/2).
+     */
+    GROUP_HANDSHAKE = 8,
+    /**
+     * This state is entered when the full authentication process is
+     * completed. In case of WPA2, this happens when the 4-Way Handshake is
+     * successfully completed. With WPA, this state is entered after the
+     * Group Key Handshake; with IEEE 802.1X (non-WPA) connection is
+     * completed after dynamic keys are received (or if not used, after
+     * the EAP authentication has been completed). With static WEP keys and
+     * plaintext connections, this state is entered when an association
+     * has been completed.
+     *
+     * This state indicates that the supplicant has completed its
+     * processing for the association phase and that data connection is
+     * fully configured.
+     */
+    COMPLETED = 9,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/StaIfaceReasonCode.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/StaIfaceReasonCode.aidl
new file mode 100644
index 0000000..6b05c07
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/StaIfaceReasonCode.aidl
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * Reason codes (IEEE Std 802.11-2016, 9.4.1.7, Table 9-45).
+ */
+@VintfStability
+@Backing(type="int")
+enum StaIfaceReasonCode {
+    UNSPECIFIED = 1,
+    PREV_AUTH_NOT_VALID = 2,
+    DEAUTH_LEAVING = 3,
+    DISASSOC_DUE_TO_INACTIVITY = 4,
+    DISASSOC_AP_BUSY = 5,
+    CLASS2_FRAME_FROM_NONAUTH_STA = 6,
+    CLASS3_FRAME_FROM_NONASSOC_STA = 7,
+    DISASSOC_STA_HAS_LEFT = 8,
+    STA_REQ_ASSOC_WITHOUT_AUTH = 9,
+    PWR_CAPABILITY_NOT_VALID = 10,
+    SUPPORTED_CHANNEL_NOT_VALID = 11,
+    BSS_TRANSITION_DISASSOC = 12,
+    INVALID_IE = 13,
+    MICHAEL_MIC_FAILURE = 14,
+    FOURWAY_HANDSHAKE_TIMEOUT = 15,
+    GROUP_KEY_UPDATE_TIMEOUT = 16,
+    IE_IN_4WAY_DIFFERS = 17,
+    GROUP_CIPHER_NOT_VALID = 18,
+    PAIRWISE_CIPHER_NOT_VALID = 19,
+    AKMP_NOT_VALID = 20,
+    UNSUPPORTED_RSN_IE_VERSION = 21,
+    INVALID_RSN_IE_CAPAB = 22,
+    IEEE_802_1X_AUTH_FAILED = 23,
+    CIPHER_SUITE_REJECTED = 24,
+    TDLS_TEARDOWN_UNREACHABLE = 25,
+    TDLS_TEARDOWN_UNSPECIFIED = 26,
+    SSP_REQUESTED_DISASSOC = 27,
+    NO_SSP_ROAMING_AGREEMENT = 28,
+    BAD_CIPHER_OR_AKM = 29,
+    NOT_AUTHORIZED_THIS_LOCATION = 30,
+    SERVICE_CHANGE_PRECLUDES_TS = 31,
+    UNSPECIFIED_QOS_REASON = 32,
+    NOT_ENOUGH_BANDWIDTH = 33,
+    DISASSOC_LOW_ACK = 34,
+    EXCEEDED_TXOP = 35,
+    STA_LEAVING = 36,
+    END_TS_BA_DLS = 37,
+    UNKNOWN_TS_BA = 38,
+    TIMEOUT = 39,
+    PEERKEY_MISMATCH = 45,
+    AUTHORIZED_ACCESS_LIMIT_REACHED = 46,
+    EXTERNAL_SERVICE_REQUIREMENTS = 47,
+    INVALID_FT_ACTION_FRAME_COUNT = 48,
+    INVALID_PMKID = 49,
+    INVALID_MDE = 50,
+    INVALID_FTE = 51,
+    MESH_PEERING_CANCELLED = 52,
+    MESH_MAX_PEERS = 53,
+    MESH_CONFIG_POLICY_VIOLATION = 54,
+    MESH_CLOSE_RCVD = 55,
+    MESH_MAX_RETRIES = 56,
+    MESH_CONFIRM_TIMEOUT = 57,
+    MESH_INVALID_GTK = 58,
+    MESH_INCONSISTENT_PARAMS = 59,
+    MESH_INVALID_SECURITY_CAP = 60,
+    MESH_PATH_ERROR_NO_PROXY_INFO = 61,
+    MESH_PATH_ERROR_NO_FORWARDING_INFO = 62,
+    MESH_PATH_ERROR_DEST_UNREACHABLE = 63,
+    MAC_ADDRESS_ALREADY_EXISTS_IN_MBSS = 64,
+    MESH_CHANNEL_SWITCH_REGULATORY_REQ = 65,
+    MESH_CHANNEL_SWITCH_UNSPECIFIED = 66,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/StaIfaceStatusCode.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/StaIfaceStatusCode.aidl
new file mode 100644
index 0000000..75e7f68
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/StaIfaceStatusCode.aidl
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * Status codes (IEEE Std 802.11-2016, 9.4.1.9, Table 9-46).
+ */
+@VintfStability
+@Backing(type="int")
+enum StaIfaceStatusCode {
+    SUCCESS = 0,
+    UNSPECIFIED_FAILURE = 1,
+    TDLS_WAKEUP_ALTERNATE = 2,
+    TDLS_WAKEUP_REJECT = 3,
+    SECURITY_DISABLED = 5,
+    UNACCEPTABLE_LIFETIME = 6,
+    NOT_IN_SAME_BSS = 7,
+    CAPS_UNSUPPORTED = 10,
+    REASSOC_NO_ASSOC = 11,
+    ASSOC_DENIED_UNSPEC = 12,
+    NOT_SUPPORTED_AUTH_ALG = 13,
+    UNKNOWN_AUTH_TRANSACTION = 14,
+    CHALLENGE_FAIL = 15,
+    AUTH_TIMEOUT = 16,
+    AP_UNABLE_TO_HANDLE_NEW_STA = 17,
+    ASSOC_DENIED_RATES = 18,
+    ASSOC_DENIED_NOSHORT = 19,
+    SPEC_MGMT_REQUIRED = 22,
+    PWR_CAPABILITY_NOT_VALID = 23,
+    SUPPORTED_CHANNEL_NOT_VALID = 24,
+    ASSOC_DENIED_NO_SHORT_SLOT_TIME = 25,
+    ASSOC_DENIED_NO_HT = 27,
+    R0KH_UNREACHABLE = 28,
+    ASSOC_DENIED_NO_PCO = 29,
+    ASSOC_REJECTED_TEMPORARILY = 30,
+    ROBUST_MGMT_FRAME_POLICY_VIOLATION = 31,
+    UNSPECIFIED_QOS_FAILURE = 32,
+    DENIED_INSUFFICIENT_BANDWIDTH = 33,
+    DENIED_POOR_CHANNEL_CONDITIONS = 34,
+    DENIED_QOS_NOT_SUPPORTED = 35,
+    REQUEST_DECLINED = 37,
+    INVALID_PARAMETERS = 38,
+    REJECTED_WITH_SUGGESTED_CHANGES = 39,
+    INVALID_IE = 40,
+    GROUP_CIPHER_NOT_VALID = 41,
+    PAIRWISE_CIPHER_NOT_VALID = 42,
+    AKMP_NOT_VALID = 43,
+    UNSUPPORTED_RSN_IE_VERSION = 44,
+    INVALID_RSN_IE_CAPAB = 45,
+    CIPHER_REJECTED_PER_POLICY = 46,
+    TS_NOT_CREATED = 47,
+    DIRECT_LINK_NOT_ALLOWED = 48,
+    DEST_STA_NOT_PRESENT = 49,
+    DEST_STA_NOT_QOS_STA = 50,
+    ASSOC_DENIED_LISTEN_INT_TOO_LARGE = 51,
+    INVALID_FT_ACTION_FRAME_COUNT = 52,
+    INVALID_PMKID = 53,
+    INVALID_MDIE = 54,
+    INVALID_FTIE = 55,
+    REQUESTED_TCLAS_NOT_SUPPORTED = 56,
+    INSUFFICIENT_TCLAS_PROCESSING_RESOURCES = 57,
+    TRY_ANOTHER_BSS = 58,
+    GAS_ADV_PROTO_NOT_SUPPORTED = 59,
+    NO_OUTSTANDING_GAS_REQ = 60,
+    GAS_RESP_NOT_RECEIVED = 61,
+    STA_TIMED_OUT_WAITING_FOR_GAS_RESP = 62,
+    GAS_RESP_LARGER_THAN_LIMIT = 63,
+    REQ_REFUSED_HOME = 64,
+    ADV_SRV_UNREACHABLE = 65,
+    REQ_REFUSED_SSPN = 67,
+    REQ_REFUSED_UNAUTH_ACCESS = 68,
+    INVALID_RSNIE = 72,
+    U_APSD_COEX_NOT_SUPPORTED = 73,
+    U_APSD_COEX_MODE_NOT_SUPPORTED = 74,
+    BAD_INTERVAL_WITH_U_APSD_COEX = 75,
+    ANTI_CLOGGING_TOKEN_REQ = 76,
+    FINITE_CYCLIC_GROUP_NOT_SUPPORTED = 77,
+    CANNOT_FIND_ALT_TBTT = 78,
+    TRANSMISSION_FAILURE = 79,
+    REQ_TCLAS_NOT_SUPPORTED = 80,
+    TCLAS_RESOURCES_EXCHAUSTED = 81,
+    REJECTED_WITH_SUGGESTED_BSS_TRANSITION = 82,
+    REJECT_WITH_SCHEDULE = 83,
+    REJECT_NO_WAKEUP_SPECIFIED = 84,
+    SUCCESS_POWER_SAVE_MODE = 85,
+    PENDING_ADMITTING_FST_SESSION = 86,
+    PERFORMING_FST_NOW = 87,
+    PENDING_GAP_IN_BA_WINDOW = 88,
+    REJECT_U_PID_SETTING = 89,
+    REFUSED_EXTERNAL_REASON = 92,
+    REFUSED_AP_OUT_OF_MEMORY = 93,
+    REJECTED_EMERGENCY_SERVICE_NOT_SUPPORTED = 94,
+    QUERY_RESP_OUTSTANDING = 95,
+    REJECT_DSE_BAND = 96,
+    TCLAS_PROCESSING_TERMINATED = 97,
+    TS_SCHEDULE_CONFLICT = 98,
+    DENIED_WITH_SUGGESTED_BAND_AND_CHANNEL = 99,
+    MCCAOP_RESERVATION_CONFLICT = 100,
+    MAF_LIMIT_EXCEEDED = 101,
+    MCCA_TRACK_LIMIT_EXCEEDED = 102,
+    DENIED_DUE_TO_SPECTRUM_MANAGEMENT = 103,
+    ASSOC_DENIED_NO_VHT = 104,
+    ENABLEMENT_DENIED = 105,
+    RESTRICTION_FROM_AUTHORIZED_GDB = 106,
+    AUTHORIZATION_DEENABLED = 107,
+    FILS_AUTHENTICATION_FAILURE = 112,
+    UNKNOWN_AUTHENTICATION_SERVER = 113,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/SupplicantStatusCode.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/SupplicantStatusCode.aidl
new file mode 100644
index 0000000..c7b7ffd
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/SupplicantStatusCode.aidl
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * Enum values indicating the status of any supplicant operation.
+ */
+@VintfStability
+@Backing(type="int")
+enum SupplicantStatusCode {
+    /**
+     * No errors.
+     */
+    SUCCESS,
+    /**
+     * Unknown failure occurred.
+     */
+    FAILURE_UNKNOWN,
+    /**
+     * One of the incoming args is invalid.
+     */
+    FAILURE_ARGS_INVALID,
+    /**
+     * |ISupplicantIface| AIDL interface object is no longer valid.
+     */
+    FAILURE_IFACE_INVALID,
+    /**
+     * Iface with the provided name does not exist.
+     */
+    FAILURE_IFACE_UNKNOWN,
+    /**
+     * Iface with the provided name already exists.
+     */
+    FAILURE_IFACE_EXISTS,
+    /**
+     * Iface is disabled and cannot be used.
+     */
+    FAILURE_IFACE_DISABLED,
+    /**
+     * Iface is not currently disconnected, so cannot reconnect.
+     */
+    FAILURE_IFACE_NOT_DISCONNECTED,
+    /**
+     * |ISupplicantNetwork| AIDL interface object is no longer valid.
+     */
+    FAILURE_NETWORK_INVALID,
+    /**
+     * Network with the provided id does not exist.
+     */
+    FAILURE_NETWORK_UNKNOWN,
+    FAILURE_UNSUPPORTED,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/TransitionDisableIndication.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/TransitionDisableIndication.aidl
new file mode 100644
index 0000000..baf20a8
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/TransitionDisableIndication.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * WPA3™ Specification Addendum for WPA3 R3 - Table 3.
+ * Transition Disable Indication filled in the third
+ * 4-way handshake message.
+ * See /external/wpa_supplicant_8/src/common/wpa_common.h for
+ * all possible values (starting at TRANSITION_DISABLE_WPA3_PERSONAL).
+ */
+@VintfStability
+@Backing(type="int")
+enum TransitionDisableIndication {
+    USE_WPA3_PERSONAL = 1 << 0,
+    USE_SAE_PK = 1 << 1,
+    USE_WPA3_ENTERPRISE = 1 << 2,
+    USE_ENHANCED_OPEN = 1 << 3,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WifiTechnology.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WifiTechnology.aidl
new file mode 100644
index 0000000..00c16b4
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WifiTechnology.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * Wifi Technologies
+ */
+@VintfStability
+@Backing(type="int")
+enum WifiTechnology {
+    UNKNOWN = 0,
+    /**
+     * For 802.11a/b/g
+     */
+    LEGACY = 1,
+    /**
+     * For 802.11n
+     */
+    HT = 2,
+    /**
+     * For 802.11ac
+     */
+    VHT = 3,
+    /**
+     * For 802.11ax
+     */
+    HE = 4,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpaDriverCapabilitiesMask.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpaDriverCapabilitiesMask.aidl
new file mode 100644
index 0000000..e174199
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpaDriverCapabilitiesMask.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * WPA Driver capability.
+ */
+@VintfStability
+@Backing(type="int")
+enum WpaDriverCapabilitiesMask {
+    /**
+     * Multi Band Operation.
+     */
+    MBO = 1 << 0,
+    /**
+     * Optimized Connectivity Experience.
+     */
+    OCE = 1 << 1,
+    /**
+     * WPA3 SAE Public-Key.
+     */
+    SAE_PK = 1 << 2,
+    /**
+     * Wi-Fi Display R2
+     */
+    WFD_R2 = 1 << 3,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpsConfigError.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpsConfigError.aidl
new file mode 100644
index 0000000..926946c
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpsConfigError.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * WPS Configuration Error.
+ */
+@VintfStability
+@Backing(type="int")
+enum WpsConfigError {
+    NO_ERROR = 0,
+    OOB_IFACE_READ_ERROR = 1,
+    DECRYPTION_CRC_FAILURE = 2,
+    CHAN_24_NOT_SUPPORTED = 3,
+    CHAN_50_NOT_SUPPORTED = 4,
+    SIGNAL_TOO_WEAK = 5,
+    NETWORK_AUTH_FAILURE = 6,
+    NETWORK_ASSOC_FAILURE = 7,
+    NO_DHCP_RESPONSE = 8,
+    FAILED_DHCP_CONFIG = 9,
+    IP_ADDR_CONFLICT = 10,
+    NO_CONN_TO_REGISTRAR = 11,
+    MULTIPLE_PBC_DETECTED = 12,
+    ROGUE_SUSPECTED = 13,
+    DEVICE_BUSY = 14,
+    SETUP_LOCKED = 15,
+    MSG_TIMEOUT = 16,
+    REG_SESS_TIMEOUT = 17,
+    DEV_PASSWORD_AUTH_FAILURE = 18,
+    CHAN_60G_NOT_SUPPORTED = 19,
+    PUBLIC_KEY_HASH_MISMATCH = 20,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpsConfigMethods.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpsConfigMethods.aidl
new file mode 100644
index 0000000..ec08a45
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpsConfigMethods.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * WPS config methods.
+ * Refer to section 3 of IBSS with Wi-Fi Protected Setup
+ * Technical Specification Version 1.0.0.
+ */
+@VintfStability
+@Backing(type="int")
+enum WpsConfigMethods {
+    USBA = 0x0001,
+    ETHERNET = 0x0002,
+    LABEL = 0x0004,
+    DISPLAY = 0x0008,
+    EXT_NFC_TOKEN = 0x0010,
+    INT_NFC_TOKEN = 0x0020,
+    NFC_INTERFACE = 0x0040,
+    PUSHBUTTON = 0x0080,
+    KEYPAD = 0x0100,
+    VIRT_PUSHBUTTON = 0x0280,
+    PHY_PUSHBUTTON = 0x0480,
+    P2PS = 0x1000,
+    VIRT_DISPLAY = 0x2008,
+    PHY_DISPLAY = 0x4008,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpsDevPasswordId.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpsDevPasswordId.aidl
new file mode 100644
index 0000000..ca5a533
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpsDevPasswordId.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * WPS Device Password ID
+ */
+@VintfStability
+@Backing(type="int")
+enum WpsDevPasswordId {
+    DEFAULT = 0x0000,
+    USER_SPECIFIED = 0x0001,
+    MACHINE_SPECIFIED = 0x0002,
+    REKEY = 0x0003,
+    PUSHBUTTON = 0x0004,
+    REGISTRAR_SPECIFIED = 0x0005,
+    NFC_CONNECTION_HANDOVER = 0x0007,
+    P2PS_DEFAULT = 0x0008,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpsErrorIndication.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpsErrorIndication.aidl
new file mode 100644
index 0000000..4866acc
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpsErrorIndication.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+/**
+ * Vendor specific Error Indication for WPS event messages.
+ */
+@VintfStability
+@Backing(type="int")
+enum WpsErrorIndication {
+    NO_ERROR = 0,
+    SECURITY_TKIP_ONLY_PROHIBITED = 1,
+    SECURITY_WEP_PROHIBITED = 2,
+    AUTH_FAILURE = 3,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpsProvisionMethod.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpsProvisionMethod.aidl
new file mode 100644
index 0000000..5b59392
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpsProvisionMethod.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant;
+
+@VintfStability
+@Backing(type="int")
+enum WpsProvisionMethod {
+    /**
+     * Push button method.
+     */
+    PBC,
+    /**
+     * Display pin method configuration - pin is generated and displayed on
+     * device.
+     */
+    DISPLAY,
+    /**
+     * Keypad pin method configuration - pin is entered on device.
+     */
+    KEYPAD,
+}
diff --git a/wifi/supplicant/aidl/vts/functional/Android.bp b/wifi/supplicant/aidl/vts/functional/Android.bp
new file mode 100644
index 0000000..8e142ec
--- /dev/null
+++ b/wifi/supplicant/aidl/vts/functional/Android.bp
@@ -0,0 +1,126 @@
+//
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+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: "VtsHalWifiSupplicantStaIfaceTargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    srcs: ["supplicant_sta_iface_aidl_test.cpp"],
+    shared_libs: [
+        "libbinder",
+        "libbinder_ndk",
+        "libvndksupport",
+    ],
+    static_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.supplicant@1.0",
+        "android.hardware.wifi.supplicant@1.1",
+        "android.hardware.wifi.supplicant-V1-ndk",
+        "libwifi-system",
+        "libwifi-system-iface",
+        "VtsHalWifiV1_0TargetTestUtil",
+        "VtsHalWifiV1_5TargetTestUtil",
+        "VtsHalWifiSupplicantV1_0TargetTestUtil",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
+
+cc_test {
+    name: "VtsHalWifiSupplicantStaNetworkTargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    srcs: ["supplicant_sta_network_aidl_test.cpp"],
+    shared_libs: [
+        "libbinder",
+        "libbinder_ndk",
+        "libvndksupport",
+    ],
+    static_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.supplicant@1.0",
+        "android.hardware.wifi.supplicant@1.1",
+        "android.hardware.wifi.supplicant-V1-ndk",
+        "libwifi-system",
+        "libwifi-system-iface",
+        "VtsHalWifiV1_0TargetTestUtil",
+        "VtsHalWifiV1_5TargetTestUtil",
+        "VtsHalWifiSupplicantV1_0TargetTestUtil",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
+
+cc_test {
+    name: "VtsHalWifiSupplicantP2pIfaceTargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    srcs: ["supplicant_p2p_iface_aidl_test.cpp"],
+    shared_libs: [
+        "libbinder",
+        "libbinder_ndk",
+        "libvndksupport",
+    ],
+    static_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.supplicant@1.0",
+        "android.hardware.wifi.supplicant@1.1",
+        "android.hardware.wifi.supplicant-V1-ndk",
+        "libwifi-system",
+        "libwifi-system-iface",
+        "VtsHalWifiV1_0TargetTestUtil",
+        "VtsHalWifiV1_5TargetTestUtil",
+        "VtsHalWifiSupplicantV1_0TargetTestUtil",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
diff --git a/wifi/supplicant/aidl/vts/functional/supplicant_p2p_iface_aidl_test.cpp b/wifi/supplicant/aidl/vts/functional/supplicant_p2p_iface_aidl_test.cpp
new file mode 100644
index 0000000..d5bdde2
--- /dev/null
+++ b/wifi/supplicant/aidl/vts/functional/supplicant_p2p_iface_aidl_test.cpp
@@ -0,0 +1,633 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <VtsCoreUtil.h>
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/wifi/supplicant/BnSupplicant.h>
+#include <aidl/android/hardware/wifi/supplicant/BnSupplicantP2pIfaceCallback.h>
+#include <android/binder_manager.h>
+#include <android/binder_status.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <cutils/properties.h>
+
+#include "supplicant_test_utils.h"
+
+using aidl::android::hardware::wifi::supplicant::BnSupplicantP2pIfaceCallback;
+using aidl::android::hardware::wifi::supplicant::DebugLevel;
+using aidl::android::hardware::wifi::supplicant::FreqRange;
+using aidl::android::hardware::wifi::supplicant::IfaceType;
+using aidl::android::hardware::wifi::supplicant::ISupplicant;
+using aidl::android::hardware::wifi::supplicant::ISupplicantP2pIface;
+using aidl::android::hardware::wifi::supplicant::MiracastMode;
+using aidl::android::hardware::wifi::supplicant::P2pGroupCapabilityMask;
+using aidl::android::hardware::wifi::supplicant::P2pProvDiscStatusCode;
+using aidl::android::hardware::wifi::supplicant::P2pStatusCode;
+using aidl::android::hardware::wifi::supplicant::WpsConfigMethods;
+using aidl::android::hardware::wifi::supplicant::WpsDevPasswordId;
+using aidl::android::hardware::wifi::supplicant::WpsProvisionMethod;
+using android::ProcessState;
+
+namespace {
+const std::string kTestSsidStr = "TestSsid1234";
+const std::vector<uint8_t> kTestSsid =
+    std::vector<uint8_t>(kTestSsidStr.begin(), kTestSsidStr.end());
+const std::vector<uint8_t> kTestMacAddr = {0x56, 0x67, 0x67, 0xf4, 0x56, 0x92};
+const std::vector<uint8_t> kTestPeerMacAddr = {0x56, 0x67, 0x55,
+                                               0xf4, 0x56, 0x92};
+const std::vector<uint8_t> kTestZeroMacAddr = std::vector<uint8_t>(6, 0);
+const std::string kTestPassphrase = "P2pWorld1234";
+const std::string kTestConnectPin = "34556665";
+const std::string kTestGroupIfName = "TestGroup";
+const uint32_t kTestFindTimeout = 5;
+const uint32_t kTestConnectGoIntent = 6;
+const uint32_t kTestNetworkId = 7;
+const uint32_t kTestGroupFreq = 0;
+const bool kTestGroupPersistent = false;
+const bool kTestGroupIsJoin = false;
+
+}  // namespace
+
+class SupplicantP2pIfaceCallback : public BnSupplicantP2pIfaceCallback {
+   public:
+    SupplicantP2pIfaceCallback() = default;
+
+    ::ndk::ScopedAStatus onDeviceFound(
+        const std::vector<uint8_t>& /* srcAddress */,
+        const std::vector<uint8_t>& /* p2pDeviceAddress */,
+        const std::vector<uint8_t>& /* primaryDeviceType */,
+        const std::string& /* deviceName */,
+        WpsConfigMethods /* configMethods */, int8_t /* deviceCapabilities */,
+        P2pGroupCapabilityMask /* groupCapabilities */,
+        const std::vector<uint8_t>& /* wfdDeviceInfo */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onDeviceLost(
+        const std::vector<uint8_t>& /* p2pDeviceAddress */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onFindStopped() override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onGoNegotiationCompleted(
+        P2pStatusCode /* status */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onGoNegotiationRequest(
+        const std::vector<uint8_t>& /* srcAddress */,
+        WpsDevPasswordId /* passwordId */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onGroupFormationFailure(
+        const std::string& /* failureReason */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onGroupFormationSuccess() override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onGroupRemoved(const std::string& /* groupIfname */,
+                                        bool /* isGroupOwner */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onGroupStarted(
+        const std::string& /* groupIfname */, bool /* isGroupOwner */,
+        const std::vector<uint8_t>& /* ssid */, int32_t /* frequency */,
+        const std::vector<uint8_t>& /* psk */,
+        const std::string& /* passphrase */,
+        const std::vector<uint8_t>& /* goDeviceAddress */,
+        bool /* isPersistent */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onInvitationReceived(
+        const std::vector<uint8_t>& /* srcAddress */,
+        const std::vector<uint8_t>& /* goDeviceAddress */,
+        const std::vector<uint8_t>& /* bssid */,
+        int32_t /* persistentNetworkId */,
+        int32_t /* operatingFrequency */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onInvitationResult(
+        const std::vector<uint8_t>& /* bssid */,
+        P2pStatusCode /* status */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onProvisionDiscoveryCompleted(
+        const std::vector<uint8_t>& /* p2pDeviceAddress */,
+        bool /* isRequest */, P2pProvDiscStatusCode /* status */,
+        WpsConfigMethods /* configMethods */,
+        const std::string& /* generatedPin */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onR2DeviceFound(
+        const std::vector<uint8_t>& /* srcAddress */,
+        const std::vector<uint8_t>& /* p2pDeviceAddress */,
+        const std::vector<uint8_t>& /* primaryDeviceType */,
+        const std::string& /* deviceName */,
+        WpsConfigMethods /* configMethods */, int8_t /* deviceCapabilities */,
+        P2pGroupCapabilityMask /* groupCapabilities */,
+        const std::vector<uint8_t>& /* wfdDeviceInfo */,
+        const std::vector<uint8_t>& /* wfdR2DeviceInfo */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onServiceDiscoveryResponse(
+        const std::vector<uint8_t>& /* srcAddress */,
+        char16_t /* updateIndicator */,
+        const std::vector<uint8_t>& /* tlvs */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onStaAuthorized(
+        const std::vector<uint8_t>& /* srcAddress */,
+        const std::vector<uint8_t>& /* p2pDeviceAddress */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onStaDeauthorized(
+        const std::vector<uint8_t>& /* srcAddress */,
+        const std::vector<uint8_t>& /* p2pDeviceAddress */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+};
+
+class SupplicantP2pIfaceAidlTest : public testing::TestWithParam<std::string> {
+   public:
+    void SetUp() override {
+        initializeService();
+        supplicant_ = getSupplicant(GetParam().c_str());
+        ASSERT_NE(supplicant_, nullptr);
+        ASSERT_TRUE(supplicant_
+                        ->setDebugParams(DebugLevel::EXCESSIVE,
+                                         true,  // show timestamps
+                                         true)
+                        .isOk());
+
+        bool p2pEnabled =
+            testing::deviceSupportsFeature("android.hardware.wifi.direct");
+        if (!p2pEnabled) {
+            GTEST_SKIP() << "Wi-Fi Direct is not supported, skip this test.";
+        }
+
+        EXPECT_TRUE(supplicant_->getP2pInterface(getP2pIfaceName(), &p2p_iface_)
+                        .isOk());
+        ASSERT_NE(p2p_iface_, nullptr);
+    }
+
+    void TearDown() override {
+        stopSupplicantService();
+        startWifiFramework();
+    }
+
+   protected:
+    std::shared_ptr<ISupplicant> supplicant_;
+    std::shared_ptr<ISupplicantP2pIface> p2p_iface_;
+};
+
+/*
+ * RegisterCallback
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, RegisterCallback) {
+    std::shared_ptr<SupplicantP2pIfaceCallback> callback =
+        ndk::SharedRefBase::make<SupplicantP2pIfaceCallback>();
+    ASSERT_NE(callback, nullptr);
+    EXPECT_TRUE(p2p_iface_->registerCallback(callback).isOk());
+}
+
+/*
+ * GetName
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, GetName) {
+    std::string name;
+    EXPECT_TRUE(p2p_iface_->getName(&name).isOk());
+    EXPECT_NE(name.size(), 0);
+}
+
+/*
+ * GetType
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, GetType) {
+    IfaceType type;
+    EXPECT_TRUE(p2p_iface_->getType(&type).isOk());
+    EXPECT_EQ(type, IfaceType::P2P);
+}
+
+/*
+ * GetDeviceAddress
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, GetDeviceAddress) {
+    std::vector<uint8_t> macAddr;
+    EXPECT_TRUE(p2p_iface_->getDeviceAddress(&macAddr).isOk());
+    EXPECT_EQ(macAddr.size(), 6);
+}
+
+/*
+ * GetSsid
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, GetSsid) {
+    // This will fail with fake values.
+    std::vector<uint8_t> ssid;
+    EXPECT_FALSE(p2p_iface_->getSsid(kTestMacAddr, &ssid).isOk());
+}
+
+/*
+ * GetGroupCapability
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, GetGroupCapability) {
+    // This will fail with fake values.
+    P2pGroupCapabilityMask cap;
+    EXPECT_FALSE(p2p_iface_->getGroupCapability(kTestMacAddr, &cap).isOk());
+}
+
+/*
+ * Set/Get Edmg
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, SetGetEdmg) {
+    bool emdg = false;
+    EXPECT_TRUE(p2p_iface_->setEdmg(true).isOk());
+    EXPECT_TRUE(p2p_iface_->getEdmg(&emdg).isOk());
+    EXPECT_EQ(emdg, true);
+
+    EXPECT_TRUE(p2p_iface_->setEdmg(false).isOk());
+    EXPECT_TRUE(p2p_iface_->getEdmg(&emdg).isOk());
+    EXPECT_EQ(emdg, false);
+}
+
+/*
+ * SetWpsDeviceName
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, SetWpsDeviceName) {
+    const std::string deviceName = "TestWpsDeviceName";
+    EXPECT_TRUE(p2p_iface_->setWpsDeviceName(deviceName).isOk());
+}
+
+/*
+ * SetWpsDeviceType
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, SetWpsDeviceType) {
+    const std::vector<uint8_t> deviceType = std::vector<uint8_t>(8, 0x01);
+    EXPECT_TRUE(p2p_iface_->setWpsDeviceType(deviceType).isOk());
+}
+
+/*
+ * SetWpsManufacturer
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, SetWpsManufacturer) {
+    const std::string deviceManufacturer = "TestManufacturer";
+    EXPECT_TRUE(p2p_iface_->setWpsManufacturer(deviceManufacturer).isOk());
+}
+
+/*
+ * SetWpsModelName
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, SetWpsModelName) {
+    const std::string modelName = "TestModelName";
+    EXPECT_TRUE(p2p_iface_->setWpsModelName(modelName).isOk());
+}
+
+/*
+ * SetWpsModelNumber
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, SetWpsModelNumber) {
+    const std::string modelNumber = "TestModelNumber";
+    EXPECT_TRUE(p2p_iface_->setWpsModelName(modelNumber).isOk());
+}
+
+/*
+ * SetWpsSerialNumber
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, SetWpsSerialNumber) {
+    const std::string serialNumber = "TestSerialNumber";
+    EXPECT_TRUE(p2p_iface_->setWpsSerialNumber(serialNumber).isOk());
+}
+
+/*
+ * SetWpsConfigMethods
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, SetWpsConfigMethods) {
+    const WpsConfigMethods config = WpsConfigMethods::DISPLAY;
+    EXPECT_TRUE(p2p_iface_->setWpsConfigMethods(config).isOk());
+}
+
+/*
+ * SetSsidPostfix
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, SetSsidPostfix) {
+    const std::vector<uint8_t> ssidPostfix = {'t', 'e', 's', 't'};
+    EXPECT_TRUE(p2p_iface_->setSsidPostfix(ssidPostfix).isOk());
+}
+
+/*
+ * SetWfdDeviceInfo
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, SetWfdDeviceInfo) {
+    const std::vector<uint8_t> wfdDeviceInfo = std::vector<uint8_t>(6, 0x01);
+    EXPECT_TRUE(p2p_iface_->setWfdDeviceInfo(wfdDeviceInfo).isOk());
+}
+
+/*
+ * SetWfdR2DeviceInfo
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, SetWfdR2DeviceInfo) {
+    const std::vector<uint8_t> wfdR2DeviceInfo = std::vector<uint8_t>(4, 0x01);
+    EXPECT_TRUE(p2p_iface_->setWfdR2DeviceInfo(wfdR2DeviceInfo).isOk());
+}
+
+/*
+ * SetGroupIdle
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, SetGroupIdle) {
+    // This will fail with fake values.
+    const uint32_t groupIdleTimeout = 8;
+    EXPECT_FALSE(
+        p2p_iface_->setGroupIdle(kTestGroupIfName, groupIdleTimeout).isOk());
+}
+
+/*
+ * SetPowerSave
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, SetPowerSave) {
+    // This will fail with fake values.
+    EXPECT_FALSE(p2p_iface_->setPowerSave(kTestGroupIfName, true).isOk());
+    EXPECT_FALSE(p2p_iface_->setPowerSave(kTestGroupIfName, false).isOk());
+}
+
+/*
+ * SetMiracastMode
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, SetMiracastMode) {
+    EXPECT_TRUE(p2p_iface_->setMiracastMode(MiracastMode::DISABLED).isOk());
+    EXPECT_TRUE(p2p_iface_->setMiracastMode(MiracastMode::SOURCE).isOk());
+    EXPECT_TRUE(p2p_iface_->setMiracastMode(MiracastMode::SINK).isOk());
+}
+
+/*
+ * SetDisallowedFrequencies
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, SetDisallowedFrequencies) {
+    FreqRange range1;
+    range1.min = 2412;
+    range1.max = 2432;
+    const std::vector<FreqRange> ranges = {range1};
+    EXPECT_TRUE(p2p_iface_->setDisallowedFrequencies(ranges).isOk());
+}
+
+/*
+ * SetListenChannel
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, SetListenChannel) {
+    const uint32_t testChannel = 1;
+    const uint32_t testOperatingClass = 81;
+    EXPECT_TRUE(
+        p2p_iface_->setListenChannel(testChannel, testOperatingClass).isOk());
+}
+
+/*
+ * SetMacRandomization
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, EnableMacRandomization) {
+    // Enable twice
+    EXPECT_TRUE(p2p_iface_->setMacRandomization(true).isOk());
+    EXPECT_TRUE(p2p_iface_->setMacRandomization(true).isOk());
+
+    // Disable twice
+    EXPECT_TRUE(p2p_iface_->setMacRandomization(false).isOk());
+    EXPECT_TRUE(p2p_iface_->setMacRandomization(false).isOk());
+}
+
+/*
+ * AddGroup
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, AddGroup) {
+    EXPECT_TRUE(p2p_iface_->addGroup(false, kTestNetworkId).isOk());
+}
+
+/*
+ * RemoveGroup
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, RemoveGroup) {
+    // This will fail with fake values.
+    EXPECT_FALSE(p2p_iface_->removeGroup(kTestGroupIfName).isOk());
+}
+
+/*
+ * AddGroupWithConfig - success.
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, AddGroupWithConfig_Success) {
+    EXPECT_TRUE(p2p_iface_
+                    ->addGroupWithConfig(kTestSsid, kTestPassphrase,
+                                         kTestGroupPersistent, kTestGroupFreq,
+                                         kTestZeroMacAddr, kTestGroupIsJoin)
+                    .isOk());
+}
+
+/*
+ * AddGroupWithConfig - failure due to invalid SSID.
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, AddGroupWithConfig_FailureInvalidSsid) {
+    const std::vector<uint8_t> ssid;
+    EXPECT_FALSE(p2p_iface_
+                     ->addGroupWithConfig(ssid, kTestPassphrase,
+                                          kTestGroupPersistent, kTestGroupFreq,
+                                          kTestZeroMacAddr, kTestGroupIsJoin)
+                     .isOk());
+}
+
+/*
+ * AddGroupWithConfig - failure due to invalid passphrase.
+ */
+TEST_P(SupplicantP2pIfaceAidlTest,
+       AddGroupWithConfig_FailureInvalidPassphrase) {
+    const std::string passphrase = "1234";
+    EXPECT_FALSE(p2p_iface_
+                     ->addGroupWithConfig(kTestSsid, passphrase,
+                                          kTestGroupPersistent, kTestGroupFreq,
+                                          kTestZeroMacAddr, kTestGroupIsJoin)
+                     .isOk());
+}
+
+/*
+ * AddGroupWithConfig - failure due to invalid frequency.
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, AddGroupWithConfig_FailureInvalidFrequency) {
+    const int freq = 9999;
+    EXPECT_FALSE(p2p_iface_
+                     ->addGroupWithConfig(kTestSsid, kTestPassphrase,
+                                          kTestGroupPersistent, freq,
+                                          kTestZeroMacAddr, kTestGroupIsJoin)
+                     .isOk());
+}
+
+/*
+ * Find
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, Find) {
+    EXPECT_TRUE(p2p_iface_->find(kTestFindTimeout).isOk());
+}
+
+/*
+ * StopFind
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, StopFind) {
+    EXPECT_TRUE(p2p_iface_->find(kTestFindTimeout).isOk());
+    EXPECT_TRUE(p2p_iface_->stopFind().isOk());
+}
+
+/*
+ * Flush
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, Flush) {
+    EXPECT_TRUE(p2p_iface_->flush().isOk());
+}
+
+/*
+ * Connect
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, Connect) {
+    /*
+     * Auto-join is not enabled before R. After enabling auto-join,
+     * this should always succeed.
+     */
+    std::string pin;
+    EXPECT_TRUE(p2p_iface_
+                    ->connect(kTestMacAddr, WpsProvisionMethod::PBC,
+                              kTestConnectPin, false, false,
+                              kTestConnectGoIntent, &pin)
+                    .isOk());
+}
+
+/*
+ * CancelConnect
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, CancelConnect) {
+    std::string pin;
+    EXPECT_TRUE(p2p_iface_
+                    ->connect(kTestMacAddr, WpsProvisionMethod::PBC,
+                              kTestConnectPin, false, false,
+                              kTestConnectGoIntent, &pin)
+                    .isOk());
+    EXPECT_TRUE(p2p_iface_->cancelConnect().isOk());
+}
+
+/*
+ * ProvisionDiscovery
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, ProvisionDiscovery) {
+    // This will fail with fake values.
+    EXPECT_FALSE(
+        p2p_iface_->provisionDiscovery(kTestMacAddr, WpsProvisionMethod::PBC)
+            .isOk());
+}
+
+/*
+ * Reject
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, Reject) {
+    // This will fail with fake values.
+    ASSERT_FALSE(p2p_iface_->reject(kTestMacAddr).isOk());
+}
+
+/*
+ * Invite
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, Invite) {
+    // This will fail with fake values.
+    EXPECT_FALSE(
+        p2p_iface_->invite(kTestGroupIfName, kTestMacAddr, kTestPeerMacAddr)
+            .isOk());
+}
+
+/*
+ * Reinvoke
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, Reinvoke) {
+    // This will fail with fake values.
+    EXPECT_FALSE(p2p_iface_->reinvoke(kTestNetworkId, kTestMacAddr).isOk());
+}
+
+/*
+ * ConfigureExtListen
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, ConfigureExtListen) {
+    const uint32_t extListenPeriod = 400;
+    const uint32_t extListenInterval = 400;
+    EXPECT_TRUE(
+        p2p_iface_->configureExtListen(extListenPeriod, extListenInterval)
+            .isOk());
+}
+
+/*
+ * FlushServices
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, FlushServices) {
+    EXPECT_TRUE(p2p_iface_->flushServices().isOk());
+}
+
+/*
+ * EnableWfd
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, EnableWfd) {
+    EXPECT_TRUE(p2p_iface_->enableWfd(true).isOk());
+    EXPECT_TRUE(p2p_iface_->enableWfd(false).isOk());
+}
+
+/*
+ * Add/Remove BonjourService
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, AddAndRemoveBonjourService) {
+    const std::string serviceQueryStr = "testquery";
+    const std::string serviceResponseStr = "testresponse";
+    const std::vector<uint8_t> bonjourServiceQuery =
+        std::vector<uint8_t>(serviceQueryStr.begin(), serviceQueryStr.end());
+    const std::vector<uint8_t> bonjourServiceResponse = std::vector<uint8_t>(
+        serviceResponseStr.begin(), serviceResponseStr.end());
+
+    EXPECT_TRUE(
+        p2p_iface_
+            ->addBonjourService(bonjourServiceQuery, bonjourServiceResponse)
+            .isOk());
+    EXPECT_TRUE(p2p_iface_->removeBonjourService(bonjourServiceQuery).isOk());
+
+    // This will fail because the boujour service with
+    // bonjourServiceQuery was already removed.
+    EXPECT_FALSE(p2p_iface_->removeBonjourService(bonjourServiceQuery).isOk());
+}
+
+/*
+ * Add/Remove UpnpService
+ */
+TEST_P(SupplicantP2pIfaceAidlTest, AddAndRemoveUpnpService) {
+    const std::string upnpServiceName = "TestServiceName";
+    EXPECT_TRUE(
+        p2p_iface_->addUpnpService(0 /* version */, upnpServiceName).isOk());
+    EXPECT_TRUE(
+        p2p_iface_->removeUpnpService(0 /* version */, upnpServiceName).isOk());
+
+    // This will fail because Upnp service with
+    // upnpServiceName was already removed.
+    EXPECT_FALSE(
+        p2p_iface_->removeUpnpService(0 /* version */, upnpServiceName).isOk());
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SupplicantP2pIfaceAidlTest);
+INSTANTIATE_TEST_SUITE_P(Supplicant, SupplicantP2pIfaceAidlTest,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(
+                             ISupplicant::descriptor)),
+                         android::PrintInstanceNameToString);
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    ProcessState::self()->setThreadPoolMaxThreadCount(1);
+    ProcessState::self()->startThreadPool();
+    return RUN_ALL_TESTS();
+}
diff --git a/wifi/supplicant/aidl/vts/functional/supplicant_sta_iface_aidl_test.cpp b/wifi/supplicant/aidl/vts/functional/supplicant_sta_iface_aidl_test.cpp
new file mode 100644
index 0000000..b24f502
--- /dev/null
+++ b/wifi/supplicant/aidl/vts/functional/supplicant_sta_iface_aidl_test.cpp
@@ -0,0 +1,782 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <VtsCoreUtil.h>
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/wifi/supplicant/BnSupplicant.h>
+#include <aidl/android/hardware/wifi/supplicant/BnSupplicantStaIfaceCallback.h>
+#include <android/binder_manager.h>
+#include <android/binder_status.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <cutils/properties.h>
+
+#include "supplicant_test_utils.h"
+
+using aidl::android::hardware::wifi::supplicant::AnqpInfoId;
+using aidl::android::hardware::wifi::supplicant::BnSupplicantStaIfaceCallback;
+using aidl::android::hardware::wifi::supplicant::BtCoexistenceMode;
+using aidl::android::hardware::wifi::supplicant::ConnectionCapabilities;
+using aidl::android::hardware::wifi::supplicant::DebugLevel;
+using aidl::android::hardware::wifi::supplicant::DppAkm;
+using aidl::android::hardware::wifi::supplicant::DppCurve;
+using aidl::android::hardware::wifi::supplicant::DppNetRole;
+using aidl::android::hardware::wifi::supplicant::DppResponderBootstrapInfo;
+using aidl::android::hardware::wifi::supplicant::Hs20AnqpSubtypes;
+using aidl::android::hardware::wifi::supplicant::IfaceType;
+using aidl::android::hardware::wifi::supplicant::ISupplicant;
+using aidl::android::hardware::wifi::supplicant::ISupplicantStaIface;
+using aidl::android::hardware::wifi::supplicant::ISupplicantStaNetwork;
+using aidl::android::hardware::wifi::supplicant::KeyMgmtMask;
+using aidl::android::hardware::wifi::supplicant::RxFilterType;
+using aidl::android::hardware::wifi::supplicant::WpaDriverCapabilitiesMask;
+using aidl::android::hardware::wifi::supplicant::WpsConfigMethods;
+using android::ProcessState;
+
+static constexpr int TIMEOUT_PERIOD = 60;
+class IfaceDppCallback;
+
+namespace {
+const std::vector<uint8_t> kTestMacAddr = {0x56, 0x67, 0x67, 0xf4, 0x56, 0x92};
+const std::string kTestUri =
+    "DPP:C:81/1,117/"
+    "40;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj"
+    "0DAQcDIgAD0edY4X3N//HhMFYsZfMbQJTiNFtNIWF/cIwMB/gzqOM=;;";
+}  // namespace
+
+class SupplicantStaIfaceCallback : public BnSupplicantStaIfaceCallback {
+   public:
+    SupplicantStaIfaceCallback() = default;
+
+    ::ndk::ScopedAStatus onAnqpQueryDone(
+        const std::vector<uint8_t>& /* bssid */,
+        const ::aidl::android::hardware::wifi::supplicant::AnqpData& /* data */,
+        const ::aidl::android::hardware::wifi::supplicant::
+            Hs20AnqpData& /* hs20Data */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onAssociationRejected(
+        const ::aidl::android::hardware::wifi::supplicant::
+            AssociationRejectionData& /* assocRejectData */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onAuthenticationTimeout(
+        const std::vector<uint8_t>& /* bssid */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onBssTmHandlingDone(
+        const ::aidl::android::hardware::wifi::supplicant::
+            BssTmData& /* tmData */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onBssidChanged(
+        ::aidl::android::hardware::wifi::supplicant::
+            BssidChangeReason /* reason */,
+        const std::vector<uint8_t>& /* bssid */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onDisconnected(
+        const std::vector<uint8_t>& /* bssid */, bool /* locallyGenerated */,
+        ::aidl::android::hardware::wifi::supplicant::
+            StaIfaceReasonCode /* reasonCode */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onDppFailure(
+        ::aidl::android::hardware::wifi::supplicant::DppFailureCode /* code */,
+        const std::string& /* ssid */, const std::string& /* channelList */,
+        const std::vector<char16_t>& /* bandList */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onDppProgress(
+        ::aidl::android::hardware::wifi::supplicant::DppProgressCode /* code */)
+        override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onDppSuccess(
+        ::aidl::android::hardware::wifi::supplicant::DppEventType /* type */)
+        override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onDppSuccessConfigReceived(
+        const std::vector<uint8_t>& /* ssid */,
+        const std::string& /* password */,
+        const std::vector<uint8_t>& /* psk */,
+        ::aidl::android::hardware::wifi::supplicant::DppAkm /* securityAkm */)
+        override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onDppSuccessConfigSent() override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onEapFailure(int32_t /* errorCode */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onExtRadioWorkStart(int32_t /* id */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onExtRadioWorkTimeout(int32_t /* id */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onHs20DeauthImminentNotice(
+        const std::vector<uint8_t>& /* bssid */, int32_t /* reasonCode */,
+        int32_t /* reAuthDelayInSec */, const std::string& /* url */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onHs20IconQueryDone(
+        const std::vector<uint8_t>& /* bssid */,
+        const std::string& /* fileName */,
+        const std::vector<uint8_t>& /* data */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onHs20SubscriptionRemediation(
+        const std::vector<uint8_t>& /* bssid */,
+        ::aidl::android::hardware::wifi::supplicant::OsuMethod /* osuMethod */,
+        const std::string& /* url */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus
+    onHs20TermsAndConditionsAcceptanceRequestedNotification(
+        const std::vector<uint8_t>& /* bssid */,
+        const std::string& /* url */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onNetworkAdded(int32_t /* id */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onNetworkNotFound(
+        const std::vector<uint8_t>& /* ssid */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onNetworkRemoved(int32_t /* id */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onPmkCacheAdded(
+        int64_t /* expirationTimeInSec */,
+        const std::vector<uint8_t>& /* serializedEntry */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onStateChanged(
+        ::aidl::android::hardware::wifi::supplicant::
+            StaIfaceCallbackState /* newState */,
+        const std::vector<uint8_t>& /* bssid */, int32_t /* id */,
+        const std::vector<uint8_t>& /* ssid */,
+        bool /* filsHlpSent */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onWpsEventFail(
+        const std::vector<uint8_t>& /* bssid */,
+        ::aidl::android::hardware::wifi::supplicant::
+            WpsConfigError /* configError */,
+        ::aidl::android::hardware::wifi::supplicant::
+            WpsErrorIndication /* errorInd */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onWpsEventPbcOverlap() override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onWpsEventSuccess() override {
+        return ndk::ScopedAStatus::ok();
+    }
+};
+
+class SupplicantStaIfaceAidlTest : public testing::TestWithParam<std::string> {
+   public:
+    void SetUp() override {
+        initializeService();
+        supplicant_ = getSupplicant(GetParam().c_str());
+        ASSERT_NE(supplicant_, nullptr);
+        ASSERT_TRUE(supplicant_
+                        ->setDebugParams(DebugLevel::EXCESSIVE,
+                                         true,  // show timestamps
+                                         true)
+                        .isOk());
+        EXPECT_TRUE(supplicant_->getStaInterface(getStaIfaceName(), &sta_iface_)
+                        .isOk());
+        ASSERT_NE(sta_iface_, nullptr);
+    }
+
+    void TearDown() override {
+        stopSupplicantService();
+        startWifiFramework();
+    }
+
+    enum DppCallbackType {
+        ANY_CALLBACK = -2,
+        INVALID = -1,
+        EVENT_SUCCESS = 0,
+        EVENT_PROGRESS,
+        EVENT_FAILURE,
+    };
+
+    DppCallbackType dppCallbackType;
+    uint32_t code;
+
+    // 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(DppCallbackType waitForCallbackType) {
+        std::unique_lock<std::mutex> lock(mtx_);
+        EXPECT_NE(INVALID, waitForCallbackType);  // can't ASSERT in a
+                                                  // non-void-returning method
+        auto now = std::chrono::system_clock::now();
+        std::cv_status status =
+            cv_.wait_until(lock, now + std::chrono::seconds(TIMEOUT_PERIOD));
+        return status;
+    }
+
+   protected:
+    std::shared_ptr<ISupplicant> supplicant_;
+    std::shared_ptr<ISupplicantStaIface> sta_iface_;
+
+   private:
+    // synchronization objects
+    std::mutex mtx_;
+    std::condition_variable cv_;
+};
+
+/*
+ * RegisterCallback
+ */
+TEST_P(SupplicantStaIfaceAidlTest, RegisterCallback) {
+    std::shared_ptr<SupplicantStaIfaceCallback> callback =
+        ndk::SharedRefBase::make<SupplicantStaIfaceCallback>();
+    ASSERT_NE(callback, nullptr);
+    EXPECT_TRUE(sta_iface_->registerCallback(callback).isOk());
+}
+
+/*
+ * GetConnectionCapabilities
+ */
+TEST_P(SupplicantStaIfaceAidlTest, GetConnectionCapabilities) {
+    ConnectionCapabilities cap;
+    EXPECT_TRUE(sta_iface_->getConnectionCapabilities(&cap).isOk());
+}
+
+/*
+ * GetWpaDriverCapabilities
+ */
+TEST_P(SupplicantStaIfaceAidlTest, GetWpaDriverCapabilities) {
+    WpaDriverCapabilitiesMask cap;
+    EXPECT_TRUE(sta_iface_->getWpaDriverCapabilities(&cap).isOk());
+}
+
+/*
+ * GetKeyMgmtCapabilities
+ */
+TEST_P(SupplicantStaIfaceAidlTest, GetKeyMgmtCapabilities) {
+    KeyMgmtMask cap;
+    EXPECT_TRUE(sta_iface_->getKeyMgmtCapabilities(&cap).isOk());
+
+    // Even though capabilities vary, these two are always set.
+    EXPECT_TRUE(!!(static_cast<uint32_t>(cap) &
+                   static_cast<uint32_t>(KeyMgmtMask::NONE)));
+    EXPECT_TRUE(!!(static_cast<uint32_t>(cap) &
+                   static_cast<uint32_t>(KeyMgmtMask::IEEE8021X)));
+}
+
+/*
+ * GetName
+ */
+TEST_P(SupplicantStaIfaceAidlTest, GetName) {
+    std::string name;
+    EXPECT_TRUE(sta_iface_->getName(&name).isOk());
+    EXPECT_NE(name.size(), 0);
+}
+
+/*
+ * GetType
+ */
+TEST_P(SupplicantStaIfaceAidlTest, GetType) {
+    IfaceType type;
+    EXPECT_TRUE(sta_iface_->getType(&type).isOk());
+    EXPECT_EQ(type, IfaceType::STA);
+}
+
+/*
+ * GetMacAddress
+ */
+TEST_P(SupplicantStaIfaceAidlTest, GetMacAddress) {
+    std::vector<uint8_t> macAddr;
+    EXPECT_TRUE(sta_iface_->getMacAddress(&macAddr).isOk());
+    EXPECT_EQ(macAddr.size(), 6);
+}
+
+/*
+ * ListNetworks
+ */
+TEST_P(SupplicantStaIfaceAidlTest, ListNetworks) {
+    std::vector<int32_t> networks;
+    EXPECT_TRUE(sta_iface_->listNetworks(&networks).isOk());
+}
+
+/*
+ * SetBtCoexistenceMode
+ */
+TEST_P(SupplicantStaIfaceAidlTest, SetBtCoexistenceMode) {
+    EXPECT_TRUE(
+        sta_iface_->setBtCoexistenceMode(BtCoexistenceMode::ENABLED).isOk());
+    EXPECT_TRUE(
+        sta_iface_->setBtCoexistenceMode(BtCoexistenceMode::DISABLED).isOk());
+    EXPECT_TRUE(
+        sta_iface_->setBtCoexistenceMode(BtCoexistenceMode::SENSE).isOk());
+}
+
+/*
+ * SetBtCoexistenceScanModeEnabled
+ */
+TEST_P(SupplicantStaIfaceAidlTest, SetBtCoexistenceScanModeEnabled) {
+    EXPECT_TRUE(sta_iface_->setBtCoexistenceScanModeEnabled(true).isOk());
+    EXPECT_TRUE(sta_iface_->setBtCoexistenceScanModeEnabled(false).isOk());
+}
+
+/*
+ * SetSuspendModeEnabled
+ */
+TEST_P(SupplicantStaIfaceAidlTest, SetSuspendModeEnabled) {
+    EXPECT_TRUE(sta_iface_->setSuspendModeEnabled(true).isOk());
+    EXPECT_TRUE(sta_iface_->setSuspendModeEnabled(false).isOk());
+}
+
+/*
+ * SetCountryCode
+ */
+TEST_P(SupplicantStaIfaceAidlTest, SetCountryCode) {
+    const std::vector<uint8_t> countryCode = {'M', 'X'};
+    EXPECT_TRUE(sta_iface_->setCountryCode(countryCode).isOk());
+}
+
+/*
+ * SetWpsDeviceName
+ */
+TEST_P(SupplicantStaIfaceAidlTest, SetWpsDeviceName) {
+    const std::string deviceName = "TestWpsDeviceName";
+    EXPECT_TRUE(sta_iface_->setWpsDeviceName(deviceName).isOk());
+}
+
+/*
+ * SetWpsDeviceType
+ */
+TEST_P(SupplicantStaIfaceAidlTest, SetWpsDeviceType) {
+    const std::vector<uint8_t> deviceType = {8, 0x1};
+    EXPECT_TRUE(sta_iface_->setWpsDeviceType(deviceType).isOk());
+}
+
+/*
+ * SetWpsManufacturer
+ */
+TEST_P(SupplicantStaIfaceAidlTest, SetWpsManufacturer) {
+    const std::string wpsManufacturer = "TestManufacturer";
+    EXPECT_TRUE(sta_iface_->setWpsManufacturer(wpsManufacturer).isOk());
+}
+
+/*
+ * SetWpsModelName
+ */
+TEST_P(SupplicantStaIfaceAidlTest, SetWpsModelName) {
+    const std::string modelName = "TestModelName";
+    EXPECT_TRUE(sta_iface_->setWpsModelName(modelName).isOk());
+}
+
+/*
+ * SetWpsModelNumber
+ */
+TEST_P(SupplicantStaIfaceAidlTest, SetWpsModelNumber) {
+    const std::string modelNumber = "TestModelNumber";
+    EXPECT_TRUE(sta_iface_->setWpsModelNumber(modelNumber).isOk());
+}
+
+/*
+ * SetWpsSerialNumber
+ */
+TEST_P(SupplicantStaIfaceAidlTest, SetWpsSerialNumber) {
+    const std::string serialNumber = "TestSerialNumber";
+    EXPECT_TRUE(sta_iface_->setWpsSerialNumber(serialNumber).isOk());
+}
+
+/*
+ * SetWpsConfigMethods
+ */
+TEST_P(SupplicantStaIfaceAidlTest, SetWpsConfigMethods) {
+    const WpsConfigMethods configMethods = WpsConfigMethods::KEYPAD;
+    EXPECT_TRUE(sta_iface_->setWpsConfigMethods(configMethods).isOk());
+}
+
+/*
+ * SetExternalSim
+ */
+TEST_P(SupplicantStaIfaceAidlTest, SetExternalSim) {
+    EXPECT_TRUE(sta_iface_->setExternalSim(true).isOk());
+    EXPECT_TRUE(sta_iface_->setExternalSim(false).isOk());
+}
+
+/*
+ * SetMboCellularDataStatus
+ */
+TEST_P(SupplicantStaIfaceAidlTest, SetMboCellularDataStatus) {
+    WpaDriverCapabilitiesMask cap;
+    EXPECT_TRUE(sta_iface_->getWpaDriverCapabilities(&cap).isOk());
+
+    // Operation should succeed if MBO is supported, or fail if it's not.
+    bool mboSupported =
+        !!(static_cast<uint32_t>(cap) &
+           static_cast<uint32_t>(WpaDriverCapabilitiesMask::MBO));
+    EXPECT_EQ(mboSupported, sta_iface_->setMboCellularDataStatus(true).isOk());
+}
+
+/*
+ * InitiateTdlsDiscover
+ */
+TEST_P(SupplicantStaIfaceAidlTest, InitiateTdlsDiscover) {
+    EXPECT_TRUE(sta_iface_->initiateTdlsDiscover(kTestMacAddr).isOk());
+}
+
+/*
+ * InitiateTdlsSetup
+ */
+TEST_P(SupplicantStaIfaceAidlTest, InitiateTdlsSetup) {
+    EXPECT_TRUE(sta_iface_->initiateTdlsSetup(kTestMacAddr).isOk());
+}
+
+/*
+ * InitiateTdlsTeardown
+ */
+TEST_P(SupplicantStaIfaceAidlTest, InitiateTdlsTeardown) {
+    EXPECT_TRUE(sta_iface_->initiateTdlsTeardown(kTestMacAddr).isOk());
+}
+
+/*
+ * InitiateAnqpQuery
+ */
+TEST_P(SupplicantStaIfaceAidlTest, InitiateAnqpQuery) {
+    const std::vector<AnqpInfoId> anqpIds = {
+        AnqpInfoId::VENUE_NAME, AnqpInfoId::NAI_REALM, AnqpInfoId::DOMAIN_NAME};
+    const std::vector<Hs20AnqpSubtypes> hsTypes = {
+        Hs20AnqpSubtypes::WAN_METRICS,
+        Hs20AnqpSubtypes::OPERATOR_FRIENDLY_NAME};
+
+    // Request should fail since the BSSID mentioned
+    // is not present in the scan results
+    EXPECT_FALSE(
+        sta_iface_->initiateAnqpQuery(kTestMacAddr, anqpIds, hsTypes).isOk());
+}
+
+/*
+ * InitiateHs20IconQuery
+ */
+TEST_P(SupplicantStaIfaceAidlTest, InitiateHs20IconQuery) {
+    // Request should fail since the BSSID mentioned
+    // is not present in the scan results
+    const std::string hs20IconFile = "TestFile";
+    EXPECT_FALSE(
+        sta_iface_->initiateHs20IconQuery(kTestMacAddr, hs20IconFile).isOk());
+}
+
+/*
+ * InitiateVenueUrlAnqpQuery.
+ */
+TEST_P(SupplicantStaIfaceAidlTest, InitiateVenueUrlAnqpQuery) {
+    // Request should fail since the BSSID mentioned
+    // is not present in the scan results
+    EXPECT_FALSE(sta_iface_->initiateVenueUrlAnqpQuery(kTestMacAddr).isOk());
+}
+
+/*
+ * Reassociate
+ */
+TEST_P(SupplicantStaIfaceAidlTest, Reassociate) {
+    EXPECT_TRUE(sta_iface_->reassociate().isOk());
+}
+
+/*
+ * Reconnect
+ */
+TEST_P(SupplicantStaIfaceAidlTest, Reconnect) {
+    EXPECT_FALSE(sta_iface_->reconnect().isOk());
+}
+
+/*
+ * Disconnect
+ */
+TEST_P(SupplicantStaIfaceAidlTest, Disconnect) {
+    EXPECT_TRUE(sta_iface_->disconnect().isOk());
+}
+
+/*
+ * SetPowerSave
+ */
+TEST_P(SupplicantStaIfaceAidlTest, SetPowerSave) {
+    EXPECT_TRUE(sta_iface_->setPowerSave(true).isOk());
+    EXPECT_TRUE(sta_iface_->setPowerSave(false).isOk());
+}
+
+/*
+ * StartRxFilter
+ */
+TEST_P(SupplicantStaIfaceAidlTest, StartRxFilter) {
+    EXPECT_TRUE(sta_iface_->startRxFilter().isOk());
+}
+
+/*
+ * StopRxFilter
+ */
+TEST_P(SupplicantStaIfaceAidlTest, StopRxFilter) {
+    EXPECT_TRUE(sta_iface_->stopRxFilter().isOk());
+}
+
+/*
+ * AddRxFilter
+ */
+TEST_P(SupplicantStaIfaceAidlTest, AddRxFilter) {
+    EXPECT_TRUE(sta_iface_->addRxFilter(RxFilterType::V4_MULTICAST).isOk());
+    EXPECT_TRUE(sta_iface_->addRxFilter(RxFilterType::V6_MULTICAST).isOk());
+}
+
+/*
+ * RemoveRxFilter
+ */
+TEST_P(SupplicantStaIfaceAidlTest, RemoveRxFilter) {
+    EXPECT_TRUE(sta_iface_->removeRxFilter(RxFilterType::V4_MULTICAST).isOk());
+    EXPECT_TRUE(sta_iface_->removeRxFilter(RxFilterType::V6_MULTICAST).isOk());
+}
+
+/*
+ * AddExtRadioWork
+ */
+TEST_P(SupplicantStaIfaceAidlTest, AddExtRadioWork) {
+    const std::string radioWorkName = "TestRadioWork";
+    const int32_t radioWorkFreq = 2412;
+    const int32_t radioWorkTimeout = 8;
+    int32_t radioWorkId;
+    EXPECT_TRUE(sta_iface_
+                    ->addExtRadioWork(radioWorkName, radioWorkFreq,
+                                      radioWorkTimeout, &radioWorkId)
+                    .isOk());
+    // removeExtRadio only succeeds if the added radio work hasn't started yet,
+    // so there is no guaranteed result from calling removeExtRadioWork here.
+    // Given that, we can't currently test removeExtRadioWork following
+    // a call to addExtRadioWork.
+}
+
+/*
+ * RemoveExtRadioWork
+ */
+TEST_P(SupplicantStaIfaceAidlTest, RemoveExtRadioWork) {
+    // This fails because there is no ongoing radio work with radioWorkId
+    const int32_t radioWorkId = 16;
+    EXPECT_FALSE(sta_iface_->removeExtRadioWork(radioWorkId).isOk());
+}
+
+/*
+ * Add/Remove DppPeerUri
+ */
+TEST_P(SupplicantStaIfaceAidlTest, AddRemoveDppPeerUri) {
+    if (!keyMgmtSupported(sta_iface_, KeyMgmtMask::DPP)) {
+        GTEST_SKIP() << "Missing DPP support";
+    }
+    // Add a peer URI and then remove it.
+    int32_t peerId;
+    EXPECT_TRUE(sta_iface_->addDppPeerUri(kTestUri, &peerId).isOk());
+    EXPECT_TRUE(sta_iface_->removeDppUri(peerId).isOk());
+}
+
+/*
+ * FilsHlpAddRequest
+ */
+TEST_P(SupplicantStaIfaceAidlTest, FilsHlpAddRequest) {
+    if (!isFilsSupported(sta_iface_)) {
+        GTEST_SKIP()
+            << "Skipping test since driver/supplicant doesn't support FILS";
+    }
+    const std::vector<uint8_t> destMacAddr = {0x00, 0x11, 0x22,
+                                              0x33, 0x44, 0x55};
+    const std::vector<uint8_t> pktBuffer = std::vector<uint8_t>(300, 0x3a);
+    EXPECT_TRUE(sta_iface_->filsHlpAddRequest(destMacAddr, pktBuffer).isOk());
+}
+
+/*
+ * FilsHlpFlushRequest
+ */
+TEST_P(SupplicantStaIfaceAidlTest, FilsHlpFlushRequest) {
+    if (!isFilsSupported(sta_iface_)) {
+        GTEST_SKIP()
+            << "Skipping test since driver/supplicant doesn't support FILS";
+    }
+    EXPECT_TRUE(sta_iface_->filsHlpFlushRequest().isOk());
+}
+
+/*
+ * StartDppEnrolleeResponder
+ */
+TEST_P(SupplicantStaIfaceAidlTest, StartDppEnrolleeResponder) {
+    if (!keyMgmtSupported(sta_iface_, KeyMgmtMask::DPP)) {
+        GTEST_SKIP() << "Missing DPP support";
+    }
+
+    const std::string deviceInfo = "DPP_Responder_Mode_VTS_Test";
+    const std::vector<uint8_t> mac_address = {0x22, 0x33, 0x44,
+                                              0x55, 0x66, 0x77};
+
+    // Generate DPP bootstrap information.
+    DppResponderBootstrapInfo bootstrapInfo;
+    EXPECT_TRUE(
+        sta_iface_
+            ->generateDppBootstrapInfoForResponder(
+                mac_address, deviceInfo, DppCurve::PRIME256V1, &bootstrapInfo)
+            .isOk());
+    EXPECT_NE(-1, bootstrapInfo.bootstrapId);
+    EXPECT_NE(0, bootstrapInfo.bootstrapId);
+    EXPECT_NE(0, bootstrapInfo.listenChannel);
+    const uint32_t bootstrap_id = bootstrapInfo.bootstrapId;
+    const uint32_t listen_channel = bootstrapInfo.listenChannel;
+
+    // Start DPP as Enrollee-Responder.
+    EXPECT_TRUE(sta_iface_->startDppEnrolleeResponder(listen_channel).isOk());
+
+    // Stop DPP Enrollee-Responder mode, ie remove the URI and stop listen.
+    EXPECT_TRUE(sta_iface_->stopDppResponder(bootstrap_id).isOk());
+}
+
+class IfaceDppCallback : public SupplicantStaIfaceCallback {
+    SupplicantStaIfaceAidlTest& parent_;
+    ::ndk::ScopedAStatus onDppSuccess(
+        ::aidl::android::hardware::wifi::supplicant::DppEventType event)
+        override {
+        parent_.code = (uint32_t)event;
+        parent_.dppCallbackType =
+            SupplicantStaIfaceAidlTest::DppCallbackType::EVENT_SUCCESS;
+        parent_.notify();
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onDppProgress(
+        aidl::android::hardware::wifi::supplicant::DppProgressCode code)
+        override {
+        parent_.code = (uint32_t)code;
+        parent_.dppCallbackType =
+            SupplicantStaIfaceAidlTest::DppCallbackType::EVENT_PROGRESS;
+        parent_.notify();
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onDppFailure(
+        aidl::android::hardware::wifi::supplicant::DppFailureCode code,
+        const std::string& ssid __attribute__((unused)),
+        const std::string& channelList __attribute__((unused)),
+        const std::vector<char16_t>& bandList
+        __attribute__((unused))) override {
+        parent_.code = (uint32_t)code;
+        parent_.dppCallbackType =
+            SupplicantStaIfaceAidlTest::DppCallbackType::EVENT_FAILURE;
+        parent_.notify();
+        return ndk::ScopedAStatus::ok();
+    }
+
+   public:
+    IfaceDppCallback(SupplicantStaIfaceAidlTest& parent) : parent_(parent){};
+};
+
+/*
+ * StartDppEnrolleeInitiator
+ */
+TEST_P(SupplicantStaIfaceAidlTest, StartDppEnrolleeInitiator) {
+    if (!keyMgmtSupported(sta_iface_, KeyMgmtMask::DPP)) {
+        GTEST_SKIP() << "Missing DPP support";
+    }
+
+    // Register callback
+    std::shared_ptr<IfaceDppCallback> callback =
+        ndk::SharedRefBase::make<IfaceDppCallback>(*this);
+    EXPECT_NE(callback, nullptr);
+    EXPECT_TRUE(sta_iface_->registerCallback(callback).isOk());
+
+    // Add a peer URI
+    int32_t peer_id = 0;
+    EXPECT_TRUE(sta_iface_->addDppPeerUri(kTestUri, &peer_id).isOk());
+    EXPECT_NE(0, peer_id);
+    EXPECT_NE(-1, peer_id);
+
+    // Start DPP as Enrollee-Initiator. Since this operation requires two
+    // devices, we start the operation and expect a timeout.
+    EXPECT_TRUE(sta_iface_->startDppEnrolleeInitiator(peer_id, 0).isOk());
+
+    // Wait for the timeout callback
+    EXPECT_EQ(std::cv_status::no_timeout,
+              wait(SupplicantStaIfaceAidlTest::DppCallbackType::EVENT_FAILURE));
+    EXPECT_EQ(SupplicantStaIfaceAidlTest::DppCallbackType::EVENT_FAILURE,
+              dppCallbackType);
+
+    // ...and then remove the peer URI.
+    EXPECT_TRUE(sta_iface_->removeDppUri(peer_id).isOk());
+}
+
+/*
+ * StartDppConfiguratorInitiator
+ */
+TEST_P(SupplicantStaIfaceAidlTest, StartDppConfiguratorInitiator) {
+    if (!keyMgmtSupported(sta_iface_, KeyMgmtMask::DPP)) {
+        GTEST_SKIP() << "Missing DPP support";
+    }
+
+    // Register callback
+    std::shared_ptr<IfaceDppCallback> callback =
+        ndk::SharedRefBase::make<IfaceDppCallback>(*this);
+    EXPECT_NE(callback, nullptr);
+    EXPECT_TRUE(sta_iface_->registerCallback(callback).isOk());
+
+    // Add a peer URI
+    int32_t peer_id = 0;
+    EXPECT_TRUE(sta_iface_->addDppPeerUri(kTestUri, &peer_id).isOk());
+    EXPECT_NE(0, peer_id);
+    EXPECT_NE(-1, peer_id);
+
+    const std::string ssid =
+        "6D795F746573745F73736964";  // 'my_test_ssid' encoded in hex
+    const std::string password =
+        "746F70736563726574";  // 'topsecret' encoded in hex
+
+    // Start DPP as Configurator-Initiator. Since this operation requires two
+    // devices, we start the operation and expect a timeout.
+    EXPECT_TRUE(sta_iface_
+                    ->startDppConfiguratorInitiator(peer_id, 0, ssid, password,
+                                                    "", DppNetRole::STA,
+                                                    DppAkm::PSK)
+                    .isOk());
+
+    // Wait for the timeout callback
+    ASSERT_EQ(std::cv_status::no_timeout,
+              wait(SupplicantStaIfaceAidlTest::DppCallbackType::EVENT_FAILURE));
+    ASSERT_EQ(SupplicantStaIfaceAidlTest::DppCallbackType::EVENT_FAILURE,
+              dppCallbackType);
+
+    // ...and then remove the peer URI.
+    EXPECT_TRUE(sta_iface_->removeDppUri(peer_id).isOk());
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SupplicantStaIfaceAidlTest);
+INSTANTIATE_TEST_SUITE_P(Supplicant, SupplicantStaIfaceAidlTest,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(
+                             ISupplicant::descriptor)),
+                         android::PrintInstanceNameToString);
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    ProcessState::self()->setThreadPoolMaxThreadCount(1);
+    ProcessState::self()->startThreadPool();
+    return RUN_ALL_TESTS();
+}
diff --git a/wifi/supplicant/aidl/vts/functional/supplicant_sta_network_aidl_test.cpp b/wifi/supplicant/aidl/vts/functional/supplicant_sta_network_aidl_test.cpp
new file mode 100644
index 0000000..a19b300
--- /dev/null
+++ b/wifi/supplicant/aidl/vts/functional/supplicant_sta_network_aidl_test.cpp
@@ -0,0 +1,791 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <VtsCoreUtil.h>
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/wifi/supplicant/BnSupplicant.h>
+#include <aidl/android/hardware/wifi/supplicant/BnSupplicantStaNetworkCallback.h>
+#include <android/binder_manager.h>
+#include <android/binder_status.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <cutils/properties.h>
+
+#include "supplicant_test_utils.h"
+
+using aidl::android::hardware::wifi::supplicant::AuthAlgMask;
+using aidl::android::hardware::wifi::supplicant::BnSupplicantStaNetworkCallback;
+using aidl::android::hardware::wifi::supplicant::DebugLevel;
+using aidl::android::hardware::wifi::supplicant::EapMethod;
+using aidl::android::hardware::wifi::supplicant::EapPhase2Method;
+using aidl::android::hardware::wifi::supplicant::GroupCipherMask;
+using aidl::android::hardware::wifi::supplicant::GroupMgmtCipherMask;
+using aidl::android::hardware::wifi::supplicant::IfaceType;
+using aidl::android::hardware::wifi::supplicant::ISupplicant;
+using aidl::android::hardware::wifi::supplicant::ISupplicantStaIface;
+using aidl::android::hardware::wifi::supplicant::ISupplicantStaNetwork;
+using aidl::android::hardware::wifi::supplicant::KeyMgmtMask;
+using aidl::android::hardware::wifi::supplicant::
+    NetworkRequestEapSimGsmAuthParams;
+using aidl::android::hardware::wifi::supplicant::
+    NetworkRequestEapSimUmtsAuthParams;
+using aidl::android::hardware::wifi::supplicant::
+    NetworkResponseEapSimGsmAuthParams;
+using aidl::android::hardware::wifi::supplicant::
+    NetworkResponseEapSimUmtsAuthParams;
+using aidl::android::hardware::wifi::supplicant::OcspType;
+using aidl::android::hardware::wifi::supplicant::PairwiseCipherMask;
+using aidl::android::hardware::wifi::supplicant::ProtoMask;
+using aidl::android::hardware::wifi::supplicant::SaeH2eMode;
+using aidl::android::hardware::wifi::supplicant::TransitionDisableIndication;
+using aidl::android::hardware::wifi::supplicant::WpaDriverCapabilitiesMask;
+using android::ProcessState;
+
+namespace {
+const std::vector<uint8_t> kTestIdentity = {0x45, 0x67, 0x98, 0x67, 0x56};
+const std::vector<uint8_t> kTestEncryptedIdentity = {0x35, 0x37, 0x58, 0x57,
+                                                     0x26};
+const std::string kTestSsidStr = "TestSsid1234";
+const std::vector<uint8_t> kTestSsid =
+    std::vector<uint8_t>(kTestSsidStr.begin(), kTestSsidStr.end());
+const std::vector<uint8_t> kTestBssid = {0x56, 0x67, 0x67, 0xf4, 0x56, 0x92};
+const std::string kTestPskPassphrase =
+    "\"123456780abcdef0123456780abcdef0deadbeef\"";
+const std::string kTestEapCert = "keystore://CERT";
+const std::string kTestEapMatch = "match";
+const KeyMgmtMask kTestKeyMgmt =
+    static_cast<KeyMgmtMask>(static_cast<uint32_t>(KeyMgmtMask::WPA_PSK) |
+                             static_cast<uint32_t>(KeyMgmtMask::WPA_EAP));
+
+}  // namespace
+
+class SupplicantStaNetworkCallback : public BnSupplicantStaNetworkCallback {
+   public:
+    SupplicantStaNetworkCallback() = default;
+
+    ::ndk::ScopedAStatus onNetworkEapIdentityRequest() override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onNetworkEapSimGsmAuthRequest(
+        const NetworkRequestEapSimGsmAuthParams& /* params */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onNetworkEapSimUmtsAuthRequest(
+        const NetworkRequestEapSimUmtsAuthParams& /* params */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ::ndk::ScopedAStatus onTransitionDisable(
+        TransitionDisableIndication /* ind */) override {
+        return ndk::ScopedAStatus::ok();
+    }
+};
+
+class SupplicantStaNetworkAidlTest
+    : public testing::TestWithParam<std::string> {
+   public:
+    void SetUp() override {
+        initializeService();
+        supplicant_ = getSupplicant(GetParam().c_str());
+        ASSERT_NE(supplicant_, nullptr);
+        ASSERT_TRUE(supplicant_
+                        ->setDebugParams(DebugLevel::EXCESSIVE,
+                                         true,  // show timestamps
+                                         true)
+                        .isOk());
+        EXPECT_TRUE(supplicant_->getStaInterface(getStaIfaceName(), &sta_iface_)
+                        .isOk());
+        ASSERT_NE(sta_iface_, nullptr);
+        EXPECT_TRUE(sta_iface_->addNetwork(&sta_network_).isOk());
+        ASSERT_NE(sta_network_, nullptr);
+    }
+
+    void TearDown() override {
+        stopSupplicantService();
+        startWifiFramework();
+    }
+
+   protected:
+    std::shared_ptr<ISupplicant> supplicant_;
+    std::shared_ptr<ISupplicantStaIface> sta_iface_;
+    std::shared_ptr<ISupplicantStaNetwork> sta_network_;
+
+    void removeNetwork() {
+        ASSERT_NE(sta_iface_, nullptr);
+        int32_t net_id;
+        EXPECT_TRUE(sta_network_->getId(&net_id).isOk());
+        EXPECT_TRUE(sta_iface_->removeNetwork(net_id).isOk());
+    }
+};
+
+/*
+ * RegisterCallback
+ */
+TEST_P(SupplicantStaNetworkAidlTest, RegisterCallback) {
+    std::shared_ptr<SupplicantStaNetworkCallback> callback =
+        ndk::SharedRefBase::make<SupplicantStaNetworkCallback>();
+    ASSERT_NE(callback, nullptr);
+    EXPECT_TRUE(sta_network_->registerCallback(callback).isOk());
+}
+
+/*
+ * GetInterfaceName
+ */
+TEST_P(SupplicantStaNetworkAidlTest, GetInterfaceName) {
+    std::string name;
+    EXPECT_TRUE(sta_network_->getInterfaceName(&name).isOk());
+    EXPECT_NE(name.size(), 0);
+}
+
+/*
+ * GetType
+ */
+TEST_P(SupplicantStaNetworkAidlTest, GetType) {
+    IfaceType type;
+    EXPECT_TRUE(sta_network_->getType(&type).isOk());
+    EXPECT_EQ(type, IfaceType::STA);
+}
+
+/*
+ * Set/Get ScanSsid
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetScanSsid) {
+    bool scanSsid = false;
+    EXPECT_TRUE(sta_network_->setScanSsid(true).isOk());
+    EXPECT_TRUE(sta_network_->getScanSsid(&scanSsid).isOk());
+    EXPECT_TRUE(scanSsid);
+}
+
+/*
+ * Set/Get RequirePmf
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetRequirePmf) {
+    bool requirePmf = false;
+    EXPECT_TRUE(sta_network_->setRequirePmf(true).isOk());
+    EXPECT_TRUE(sta_network_->getRequirePmf(&requirePmf).isOk());
+    EXPECT_TRUE(requirePmf);
+}
+
+/*
+ * Set/Get IdStr
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetIdStr) {
+    const std::string savedIdStr = "TestIdstr";
+    EXPECT_TRUE(sta_network_->setIdStr(savedIdStr).isOk());
+
+    std::string retrievedIdStr;
+    EXPECT_TRUE(sta_network_->getIdStr(&retrievedIdStr).isOk());
+    EXPECT_EQ(retrievedIdStr, savedIdStr);
+}
+
+/*
+ * Set/Get EapMethod
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetEapMethod) {
+    const EapMethod savedMethod = EapMethod::PEAP;
+    EXPECT_TRUE(sta_network_->setEapMethod(savedMethod).isOk());
+
+    EapMethod retrievedMethod;
+    EXPECT_TRUE(sta_network_->getEapMethod(&retrievedMethod).isOk());
+    EXPECT_EQ(retrievedMethod, savedMethod);
+}
+
+/*
+ * Set/Get EapPhase2Method
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetEapPhase2Method) {
+    const EapMethod savedEapMethod = EapMethod::PEAP;
+    EXPECT_TRUE(sta_network_->setEapMethod(savedEapMethod).isOk());
+
+    const EapPhase2Method savedPhase2Method = EapPhase2Method::NONE;
+    EXPECT_TRUE(sta_network_->setEapPhase2Method(savedPhase2Method).isOk());
+
+    EapPhase2Method retrievedMethod;
+    EXPECT_TRUE(sta_network_->getEapPhase2Method(&retrievedMethod).isOk());
+    EXPECT_EQ(retrievedMethod, savedPhase2Method);
+}
+
+/*
+ * Set/Get EapIdentity
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetEapIdentity) {
+    EXPECT_TRUE(sta_network_->setEapIdentity(kTestIdentity).isOk());
+
+    std::vector<uint8_t> retrievedIdentity;
+    EXPECT_TRUE(sta_network_->getEapIdentity(&retrievedIdentity).isOk());
+    EXPECT_EQ(retrievedIdentity, kTestIdentity);
+}
+
+/*
+ * Set/Get EapAnonymousIdentity
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetEapAnonymousIdentity) {
+    EXPECT_TRUE(sta_network_->setEapAnonymousIdentity(kTestIdentity).isOk());
+
+    std::vector<uint8_t> retrievedIdentity;
+    EXPECT_TRUE(
+        sta_network_->getEapAnonymousIdentity(&retrievedIdentity).isOk());
+    EXPECT_EQ(retrievedIdentity, kTestIdentity);
+}
+
+/*
+ * Set/Get EapPassword
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetEapPassword) {
+    const std::string eapPasswdStr = "TestEapPasswd1234";
+    const std::vector<uint8_t> savedEapPasswd =
+        std::vector<uint8_t>(eapPasswdStr.begin(), eapPasswdStr.end());
+    ASSERT_TRUE(sta_network_->setEapPassword(savedEapPasswd).isOk());
+
+    std::vector<uint8_t> retrievedEapPasswd;
+    ASSERT_TRUE(sta_network_->getEapPassword(&retrievedEapPasswd).isOk());
+    ASSERT_EQ(retrievedEapPasswd, savedEapPasswd);
+}
+
+/*
+ * Set/Get EapCACert
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetEapCACert) {
+    EXPECT_TRUE(sta_network_->setEapCACert(kTestEapCert).isOk());
+
+    std::string retrievedCert;
+    EXPECT_TRUE(sta_network_->getEapCACert(&retrievedCert).isOk());
+    EXPECT_EQ(retrievedCert, kTestEapCert);
+}
+
+/*
+ * Set/Get EapCAPath
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetEapCAPath) {
+    EXPECT_TRUE(sta_network_->setEapCAPath(kTestEapCert).isOk());
+
+    std::string retrievedCert;
+    EXPECT_TRUE(sta_network_->getEapCAPath(&retrievedCert).isOk());
+    EXPECT_EQ(retrievedCert, kTestEapCert);
+}
+
+/*
+ * Set/Get EapClientCert
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetEapClientCert) {
+    EXPECT_TRUE(sta_network_->setEapClientCert(kTestEapCert).isOk());
+
+    std::string retrievedCert;
+    EXPECT_TRUE(sta_network_->getEapClientCert(&retrievedCert).isOk());
+    EXPECT_EQ(retrievedCert, kTestEapCert);
+}
+
+/*
+ * Set/Get EapPrivateKeyId
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetEapPrivateKeyId) {
+    std::string savedKeyId = "key_id";
+    EXPECT_TRUE(sta_network_->setEapPrivateKeyId(savedKeyId).isOk());
+
+    std::string retrievedKeyId;
+    EXPECT_TRUE(sta_network_->getEapPrivateKeyId(&retrievedKeyId).isOk());
+    EXPECT_EQ(retrievedKeyId, savedKeyId);
+}
+
+/*
+ * Set/Get EapAltSubjectMatch
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetEapAltSubjectMatch) {
+    EXPECT_TRUE(sta_network_->setEapAltSubjectMatch(kTestEapMatch).isOk());
+
+    std::string retrievedMatch;
+    EXPECT_TRUE(sta_network_->getEapAltSubjectMatch(&retrievedMatch).isOk());
+    EXPECT_EQ(retrievedMatch, kTestEapMatch);
+}
+
+/*
+ * Set/Get EapSubjectMatch
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetEapSubjectMatch) {
+    EXPECT_TRUE(sta_network_->setEapSubjectMatch(kTestEapMatch).isOk());
+
+    std::string retrievedMatch;
+    EXPECT_TRUE(sta_network_->getEapSubjectMatch(&retrievedMatch).isOk());
+    EXPECT_EQ(retrievedMatch, kTestEapMatch);
+}
+
+/*
+ * Set/Get EapDomainSuffixMatch
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetEapDomainSuffixMatch) {
+    EXPECT_TRUE(sta_network_->setEapDomainSuffixMatch(kTestEapMatch).isOk());
+
+    std::string retrievedMatch;
+    EXPECT_TRUE(sta_network_->getEapDomainSuffixMatch(&retrievedMatch).isOk());
+    EXPECT_EQ(retrievedMatch, kTestEapMatch);
+}
+
+/*
+ * Set/Get EapEngine
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetEapEngine) {
+    bool retrievedEapEngine = false;
+    EXPECT_TRUE(sta_network_->setEapEngine(true).isOk());
+    EXPECT_TRUE(sta_network_->getEapEngine(&retrievedEapEngine).isOk());
+    EXPECT_TRUE(retrievedEapEngine);
+}
+
+/*
+ * Set/Get EapEngineID
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetEapEngineId) {
+    const std::string savedEngineId = "engine_id";
+    EXPECT_TRUE(sta_network_->setEapEngineID(savedEngineId).isOk());
+
+    std::string retrievedId;
+    EXPECT_TRUE(sta_network_->getEapEngineId(&retrievedId).isOk());
+    EXPECT_EQ(retrievedId, savedEngineId);
+}
+
+/*
+ * Set/Get Ocsp
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetOcsp) {
+    const OcspType savedOcspType = OcspType::REQUEST_CERT_STATUS;
+    EXPECT_TRUE(sta_network_->setOcsp(savedOcspType).isOk());
+
+    const OcspType invalidOcspType = static_cast<OcspType>(-1);
+    EXPECT_FALSE(sta_network_->setOcsp(invalidOcspType).isOk());
+
+    OcspType retrievedOcspType;
+    EXPECT_TRUE(sta_network_->getOcsp(&retrievedOcspType).isOk());
+    EXPECT_EQ(retrievedOcspType, savedOcspType);
+}
+
+/*
+ * Set/Get KeyMgmt
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetKeyMgmt) {
+    KeyMgmtMask savedKeyMgmt = KeyMgmtMask::WAPI_PSK;
+    EXPECT_TRUE(sta_network_->setKeyMgmt(savedKeyMgmt).isOk());
+
+    KeyMgmtMask retrievedKeyMgmt;
+    EXPECT_TRUE(sta_network_->getKeyMgmt(&retrievedKeyMgmt).isOk());
+    EXPECT_EQ(retrievedKeyMgmt, savedKeyMgmt);
+
+    savedKeyMgmt = KeyMgmtMask::WAPI_CERT;
+    EXPECT_TRUE(sta_network_->setKeyMgmt(savedKeyMgmt).isOk());
+
+    EXPECT_TRUE(sta_network_->getKeyMgmt(&retrievedKeyMgmt).isOk());
+    EXPECT_EQ(retrievedKeyMgmt, savedKeyMgmt);
+}
+
+/*
+ * Set/Get Proto
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetProto) {
+    const ProtoMask savedProto = ProtoMask::WAPI;
+    EXPECT_TRUE(sta_network_->setProto(savedProto).isOk());
+
+    ProtoMask retrievedProto;
+    EXPECT_TRUE(sta_network_->getProto(&retrievedProto).isOk());
+    EXPECT_EQ(retrievedProto, savedProto);
+}
+
+/*
+ * Set/Get GroupCipher
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetGroupCipher) {
+    const GroupCipherMask savedCipher = GroupCipherMask::SMS4;
+    EXPECT_TRUE(sta_network_->setGroupCipher(savedCipher).isOk());
+
+    GroupCipherMask retrievedCipher;
+    EXPECT_TRUE(sta_network_->getGroupCipher(&retrievedCipher).isOk());
+    EXPECT_EQ(retrievedCipher, savedCipher);
+}
+
+/*
+ * Set/Get PairwiseCipher
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetPairwiseCipher) {
+    const PairwiseCipherMask savedCipher = PairwiseCipherMask::SMS4;
+    EXPECT_TRUE(sta_network_->setPairwiseCipher(savedCipher).isOk());
+
+    PairwiseCipherMask retrievedCipher;
+    EXPECT_TRUE(sta_network_->getPairwiseCipher(&retrievedCipher).isOk());
+    EXPECT_EQ(retrievedCipher, savedCipher);
+}
+
+/*
+ * Set/Get WapiCertSuite
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetWapiCertSuite) {
+    if (!keyMgmtSupported(sta_iface_, KeyMgmtMask::WAPI_PSK)) {
+        GTEST_SKIP() << "Skipping test since WAPI is not supported.";
+    }
+
+    const std::string savedCertSuite = "suite";
+    EXPECT_TRUE(sta_network_->setWapiCertSuite(savedCertSuite).isOk());
+
+    std::string retrievedCertSuite;
+    EXPECT_TRUE(sta_network_->getWapiCertSuite(&retrievedCertSuite).isOk());
+    EXPECT_EQ(retrievedCertSuite, savedCertSuite);
+}
+
+/*
+ * Set/Get WapiPsk
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetWapiPsk) {
+    if (!keyMgmtSupported(sta_iface_, KeyMgmtMask::WAPI_PSK)) {
+        GTEST_SKIP() << "Skipping test since WAPI is not supported.";
+    }
+
+    EXPECT_TRUE(sta_network_->setKeyMgmt(KeyMgmtMask::WAPI_PSK).isOk());
+    EXPECT_TRUE(sta_network_->setPskPassphrase(kTestPskPassphrase).isOk());
+
+    std::string retrievedPassphrase;
+    EXPECT_TRUE(sta_network_->getPskPassphrase(&retrievedPassphrase).isOk());
+    EXPECT_EQ(retrievedPassphrase, kTestPskPassphrase);
+
+    const std::string pskHex = "12345678";
+    EXPECT_TRUE(sta_network_->setPskPassphrase(pskHex).isOk());
+
+    EXPECT_TRUE(sta_network_->getPskPassphrase(&retrievedPassphrase).isOk());
+    EXPECT_EQ(retrievedPassphrase, pskHex);
+}
+
+/*
+ * Set/Get SaePassword
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetSaePassword) {
+    const std::string savedPassword = "topsecret";
+    EXPECT_TRUE(sta_network_->setSaePassword(savedPassword).isOk());
+
+    std::string retrievedPassword;
+    EXPECT_TRUE(sta_network_->getSaePassword(&retrievedPassword).isOk());
+    EXPECT_EQ(retrievedPassword, savedPassword);
+}
+
+/*
+ * Set/Get SaePasswordId
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetSaePasswordId) {
+    const std::string savedPasswdId = "id1";
+    EXPECT_TRUE(sta_network_->setSaePasswordId(savedPasswdId).isOk());
+
+    std::string retrievedPasswdId;
+    EXPECT_TRUE(sta_network_->getSaePasswordId(&retrievedPasswdId).isOk());
+    EXPECT_EQ(retrievedPasswdId, savedPasswdId);
+}
+
+/*
+ * Set/Get GroupMgmtCipher
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetGroupMgmtCipher) {
+    const GroupMgmtCipherMask savedCipher = GroupMgmtCipherMask::BIP_GMAC_256;
+    EXPECT_TRUE(sta_network_->setGroupMgmtCipher(savedCipher).isOk());
+
+    GroupMgmtCipherMask retrievedCipher;
+    EXPECT_TRUE(sta_network_->getGroupMgmtCipher(&retrievedCipher).isOk());
+    EXPECT_EQ(retrievedCipher, savedCipher);
+}
+
+/*
+ * Set/Get Ssid
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetSsid) {
+    EXPECT_TRUE(sta_network_->setSsid(kTestSsid).isOk());
+
+    std::vector<uint8_t> retrievedSsid;
+    EXPECT_TRUE(sta_network_->getSsid(&retrievedSsid).isOk());
+    EXPECT_EQ(retrievedSsid, kTestSsid);
+}
+
+/*
+ * Set/Get Bssid
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetBssid) {
+    EXPECT_TRUE(sta_network_->setBssid(kTestBssid).isOk());
+
+    std::vector<uint8_t> retrievedBssid;
+    EXPECT_TRUE(sta_network_->getBssid(&retrievedBssid).isOk());
+    EXPECT_EQ(retrievedBssid, kTestBssid);
+}
+
+/*
+ * Set/Get KeyAuthAlg
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetAuthAlg) {
+    const AuthAlgMask savedAlg =
+        static_cast<AuthAlgMask>(static_cast<uint32_t>(AuthAlgMask::OPEN) |
+                                 static_cast<uint32_t>(AuthAlgMask::SHARED));
+    EXPECT_TRUE(sta_network_->setAuthAlg(savedAlg).isOk());
+
+    AuthAlgMask retrievedAlg;
+    EXPECT_TRUE(sta_network_->getAuthAlg(&retrievedAlg).isOk());
+    EXPECT_EQ(retrievedAlg, savedAlg);
+}
+
+/*
+ * Set/Get WepTxKeyIdx
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetWepTxKeyIdx) {
+    const int32_t savedKeyIdx = 2;
+    EXPECT_TRUE(sta_network_->setWepTxKeyIdx(savedKeyIdx).isOk());
+
+    int32_t retrievedKeyIdx;
+    EXPECT_TRUE(sta_network_->getWepTxKeyIdx(&retrievedKeyIdx).isOk());
+    EXPECT_EQ(retrievedKeyIdx, savedKeyIdx);
+}
+
+/*
+ * Set SAE H2E (Hash-to-Element) mode
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetSaeH2eMode) {
+    EXPECT_TRUE(sta_network_->setSaeH2eMode(SaeH2eMode::DISABLED).isOk());
+    EXPECT_TRUE(sta_network_->setSaeH2eMode(SaeH2eMode::H2E_MANDATORY).isOk());
+    EXPECT_TRUE(sta_network_->setSaeH2eMode(SaeH2eMode::H2E_OPTIONAL).isOk());
+}
+
+/*
+ * Set/Get Psk
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetPsk) {
+    const std::vector<uint8_t> savedPsk = std::vector<uint8_t>(32, 0x12);
+    EXPECT_TRUE(sta_network_->setPsk(savedPsk).isOk());
+
+    std::vector<uint8_t> retrievedPsk;
+    EXPECT_TRUE(sta_network_->getPsk(&retrievedPsk).isOk());
+    EXPECT_EQ(retrievedPsk, savedPsk);
+}
+
+/*
+ * Set/Get WepKeys
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetGetWepKeys) {
+    const uint32_t maxKeys = 4;
+    const std::vector<uint8_t> testWepKey = {0x56, 0x67, 0x67, 0xf4, 0x56};
+
+    for (uint32_t i = 0; i < maxKeys; i++) {
+        std::vector<uint8_t> retrievedKey;
+        EXPECT_TRUE(sta_network_->setWepKey(i, testWepKey).isOk());
+        EXPECT_TRUE(sta_network_->getWepKey(i, &retrievedKey).isOk());
+        EXPECT_EQ(retrievedKey, testWepKey);
+    }
+}
+
+/*
+ * SetPmkCacheEntry
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetPmkCache) {
+    const std::vector<uint8_t> serializedEntry(128, 0);
+    EXPECT_TRUE(sta_network_->setPmkCache(serializedEntry).isOk());
+}
+
+/*
+ * SetEapErp
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetEapErp) {
+    if (!isFilsSupported(sta_iface_)) {
+        GTEST_SKIP()
+            << "Skipping test since driver/supplicant doesn't support FILS";
+    }
+    EXPECT_TRUE(sta_network_->setEapErp(true).isOk());
+}
+
+/*
+ * SetUpdateIdentifier
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetUpdateIdentifier) {
+    const uint32_t updateIdentifier = 21;
+    EXPECT_TRUE(sta_network_->setUpdateIdentifier(updateIdentifier).isOk());
+}
+
+/*
+ * SetProactiveKeyCaching
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetProactiveKeyCaching) {
+    EXPECT_TRUE(sta_network_->setProactiveKeyCaching(true).isOk());
+    EXPECT_TRUE(sta_network_->setProactiveKeyCaching(false).isOk());
+}
+
+/*
+ * EnableSuiteBEapOpenSslCiphers
+ */
+TEST_P(SupplicantStaNetworkAidlTest, EnableSuiteBEapOpenSslCiphers) {
+    EXPECT_TRUE(sta_network_->enableSuiteBEapOpenSslCiphers().isOk());
+}
+
+/*
+ * EnableTlsSuiteBEapPhase1Param
+ */
+TEST_P(SupplicantStaNetworkAidlTest, EnableTlsSuiteBEapPhase1Param) {
+    EXPECT_TRUE(sta_network_->enableTlsSuiteBEapPhase1Param(true).isOk());
+    EXPECT_TRUE(sta_network_->enableTlsSuiteBEapPhase1Param(false).isOk());
+}
+
+/*
+ * SetEapEncryptedImsiIdentity
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetEapEncryptedImsiIdentity) {
+    EXPECT_TRUE(
+        sta_network_->setEapEncryptedImsiIdentity(kTestEncryptedIdentity)
+            .isOk());
+}
+
+/*
+ * SendNetworkEapIdentityResponse
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SendNetworkEapIdentityResponse) {
+    EXPECT_TRUE(sta_network_
+                    ->sendNetworkEapIdentityResponse(kTestIdentity,
+                                                     kTestEncryptedIdentity)
+                    .isOk());
+}
+
+/*
+ * Enable SAE PK only mode
+ */
+TEST_P(SupplicantStaNetworkAidlTest, EnableSaePkOnlyMode) {
+    // Check for SAE PK support
+    WpaDriverCapabilitiesMask caps;
+    EXPECT_TRUE(sta_iface_->getWpaDriverCapabilities(&caps).isOk());
+    const bool saePkSupported =
+        !!(static_cast<uint32_t>(caps) &
+           static_cast<uint32_t>(WpaDriverCapabilitiesMask::SAE_PK));
+    LOG(INFO) << "SAE-PK Supported: " << saePkSupported;
+
+    // Operation will succeed if SAE PK is supported, or fail otherwise.
+    EXPECT_EQ(sta_network_->enableSaePkOnlyMode(true).isOk(), saePkSupported);
+    EXPECT_EQ(sta_network_->enableSaePkOnlyMode(false).isOk(), saePkSupported);
+}
+
+/*
+ * Enable
+ */
+TEST_P(SupplicantStaNetworkAidlTest, Enable) {
+    // wpa_supplicant won't perform any connection initiation
+    // unless at least the SSID and key mgmt params are set.
+    EXPECT_TRUE(sta_network_->setSsid(kTestSsid).isOk());
+    EXPECT_TRUE(sta_network_->setKeyMgmt(kTestKeyMgmt).isOk());
+
+    EXPECT_TRUE(sta_network_->enable(false).isOk());
+    EXPECT_TRUE(sta_network_->enable(true).isOk());
+
+    // Now remove the network and ensure that the call fails.
+    removeNetwork();
+    ASSERT_FALSE(sta_network_->enable(true).isOk());
+}
+
+/*
+ * Disable
+ */
+TEST_P(SupplicantStaNetworkAidlTest, Disable) {
+    // wpa_supplicant won't perform any connection initiation
+    // unless at least the SSID and key mgmt params are set.
+    EXPECT_TRUE(sta_network_->setSsid(kTestSsid).isOk());
+    EXPECT_TRUE(sta_network_->setKeyMgmt(kTestKeyMgmt).isOk());
+
+    EXPECT_TRUE(sta_network_->disable().isOk());
+
+    // Now remove the network and ensure that the call fails.
+    removeNetwork();
+    EXPECT_FALSE(sta_network_->disable().isOk());
+}
+
+/*
+ * Select
+ */
+TEST_P(SupplicantStaNetworkAidlTest, Select) {
+    // wpa_supplicant won't perform any connection initiation
+    // unless at least the SSID and key mgmt params are set.
+    EXPECT_TRUE(sta_network_->setSsid(kTestSsid).isOk());
+    EXPECT_TRUE(sta_network_->setKeyMgmt(kTestKeyMgmt).isOk());
+
+    EXPECT_TRUE(sta_network_->select().isOk());
+
+    // Now remove the network and ensure that the call fails.
+    removeNetwork();
+    EXPECT_FALSE(sta_network_->select().isOk());
+}
+
+/*
+ * SendNetworkEapSimGsmAuthResponse
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SendNetworkEapSimGsmAuthResponse) {
+    NetworkResponseEapSimGsmAuthParams param;
+    param.kc =
+        std::vector<uint8_t>({0x56, 0x67, 0x67, 0xf4, 0x76, 0x87, 0x98, 0x12});
+    param.sres = std::vector<uint8_t>({0x56, 0x67, 0x67, 0xf4});
+    const std::vector<NetworkResponseEapSimGsmAuthParams> params = {param};
+    EXPECT_TRUE(sta_network_->sendNetworkEapSimGsmAuthResponse(params).isOk());
+}
+
+/*
+ * SendNetworkEapSimGsmAuthFailure
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SendNetworkEapSimGsmAuthFailure) {
+    EXPECT_TRUE(sta_network_->sendNetworkEapSimGsmAuthFailure().isOk());
+}
+
+/*
+ * SendNetworkEapSimUmtsAuthResponse
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SendNetworkEapSimUmtsAuthResponse) {
+    NetworkResponseEapSimUmtsAuthParams params;
+    params.res = std::vector<uint8_t>({0x56, 0x67, 0x67, 0xf4, 0x67});
+    params.ik = std::vector<uint8_t>(16, 0x65);
+    params.ck = std::vector<uint8_t>(16, 0x45);
+    EXPECT_TRUE(sta_network_->sendNetworkEapSimUmtsAuthResponse(params).isOk());
+}
+
+/*
+ * SendNetworkEapSimUmtsAuthFailure
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SendNetworkEapSimUmtsAuthFailure) {
+    EXPECT_TRUE(sta_network_->sendNetworkEapSimUmtsAuthFailure().isOk());
+}
+
+/*
+ * SendNetworkEapSimUmtsAutsResponse
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SendNetworkEapSimUmtsAutsResponse) {
+    const std::vector<uint8_t> testAutParam = std::vector<uint8_t>(14, 0xe1);
+    EXPECT_TRUE(
+        sta_network_->sendNetworkEapSimUmtsAutsResponse(testAutParam).isOk());
+}
+
+/*
+ * GetWpsNfcConfigurationToken
+ */
+TEST_P(SupplicantStaNetworkAidlTest, GetWpsNfcConfigurationToken) {
+    EXPECT_TRUE(sta_network_->setSsid(kTestSsid).isOk());
+    EXPECT_TRUE(sta_network_->setKeyMgmt(kTestKeyMgmt).isOk());
+    EXPECT_TRUE(sta_network_->setPskPassphrase(kTestPskPassphrase).isOk());
+
+    std::vector<uint8_t> retrievedToken;
+    EXPECT_TRUE(
+        sta_network_->getWpsNfcConfigurationToken(&retrievedToken).isOk());
+    EXPECT_NE(retrievedToken.size(), 0);
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SupplicantStaNetworkAidlTest);
+INSTANTIATE_TEST_SUITE_P(Supplicant, SupplicantStaNetworkAidlTest,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(
+                             ISupplicant::descriptor)),
+                         android::PrintInstanceNameToString);
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    ProcessState::self()->setThreadPoolMaxThreadCount(1);
+    ProcessState::self()->startThreadPool();
+    return RUN_ALL_TESTS();
+}
diff --git a/wifi/supplicant/aidl/vts/functional/supplicant_test_utils.h b/wifi/supplicant/aidl/vts/functional/supplicant_test_utils.h
new file mode 100644
index 0000000..17e0394
--- /dev/null
+++ b/wifi/supplicant/aidl/vts/functional/supplicant_test_utils.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SUPPLICANT_TEST_UTILS_H
+#define SUPPLICANT_TEST_UTILS_H
+
+#include <VtsCoreUtil.h>
+#include <android-base/logging.h>
+#include <android/hardware/wifi/1.0/IWifi.h>
+#include <hidl/ServiceManagement.h>
+#include <supplicant_hidl_test_utils.h>
+#include <wifi_system/supplicant_manager.h>
+
+using aidl::android::hardware::wifi::supplicant::IfaceInfo;
+using aidl::android::hardware::wifi::supplicant::ISupplicant;
+using aidl::android::hardware::wifi::supplicant::ISupplicantP2pIface;
+using aidl::android::hardware::wifi::supplicant::ISupplicantStaIface;
+using aidl::android::hardware::wifi::supplicant::KeyMgmtMask;
+using android::wifi_system::SupplicantManager;
+
+std::string getStaIfaceName() {
+    std::array<char, PROPERTY_VALUE_MAX> buffer;
+    property_get("wifi.interface", buffer.data(), "wlan0");
+    return std::string(buffer.data());
+}
+
+std::string getP2pIfaceName() {
+    std::array<char, PROPERTY_VALUE_MAX> buffer;
+    property_get("wifi.direct.interface", buffer.data(), "p2p0");
+    return std::string(buffer.data());
+}
+
+std::string getWifiInstanceName() {
+    const std::vector<std::string> instances =
+        android::hardware::getAllHalInstanceNames(
+            ::android::hardware::wifi::V1_0::IWifi::descriptor);
+    EXPECT_NE(0, instances.size());
+    return instances.size() != 0 ? instances[0] : "";
+}
+
+bool keyMgmtSupported(std::shared_ptr<ISupplicantStaIface> iface,
+                      KeyMgmtMask expected) {
+    KeyMgmtMask caps;
+    if (!iface->getKeyMgmtCapabilities(&caps).isOk()) {
+        return false;
+    }
+    return !!(static_cast<uint32_t>(caps) & static_cast<uint32_t>(expected));
+}
+
+bool isFilsSupported(std::shared_ptr<ISupplicantStaIface> iface) {
+    KeyMgmtMask filsMask = static_cast<KeyMgmtMask>(
+        static_cast<uint32_t>(KeyMgmtMask::FILS_SHA256) |
+        static_cast<uint32_t>(KeyMgmtMask::FILS_SHA384));
+    return keyMgmtSupported(iface, filsMask);
+}
+
+void startSupplicant() {
+    initializeDriverAndFirmware(getWifiInstanceName());
+    SupplicantManager supplicant_manager;
+    ASSERT_TRUE(supplicant_manager.StartSupplicant());
+    ASSERT_TRUE(supplicant_manager.IsSupplicantRunning());
+}
+
+// Wrapper around the implementation in supplicant_hidl_test_util.
+void stopSupplicantService() { stopSupplicant(getWifiInstanceName()); }
+
+void initializeService() {
+    ASSERT_TRUE(stopWifiFramework());
+    std::system("/system/bin/start");
+    ASSERT_TRUE(waitForFrameworkReady());
+    stopSupplicantService();
+    startSupplicant();
+}
+
+void addStaIface(const std::shared_ptr<ISupplicant> supplicant) {
+    ASSERT_TRUE(supplicant.get());
+    std::shared_ptr<ISupplicantStaIface> iface;
+    ASSERT_TRUE(supplicant->addStaInterface(getStaIfaceName(), &iface).isOk());
+}
+
+void addP2pIface(const std::shared_ptr<ISupplicant> supplicant) {
+    ASSERT_TRUE(supplicant.get());
+    std::shared_ptr<ISupplicantP2pIface> iface;
+    ASSERT_TRUE(supplicant->addP2pInterface(getP2pIfaceName(), &iface).isOk());
+}
+
+std::shared_ptr<ISupplicant> getSupplicant(const char* supplicant_name) {
+    std::shared_ptr<ISupplicant> supplicant = ISupplicant::fromBinder(
+        ndk::SpAIBinder(AServiceManager_waitForService(supplicant_name)));
+    addStaIface(supplicant);
+    if (testing::deviceSupportsFeature("android.hardware.wifi.direct")) {
+        addP2pIface(supplicant);
+    }
+    return supplicant;
+}
+
+#endif  // SUPPLICANT_TEST_UTILS_H
\ No newline at end of file